2021-6-12金典笔记00
Posted 轻舟一曲
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-6-12金典笔记00相关的知识,希望对你有一定的参考价值。
笔记00
_01_判断字符串是否唯一
实现一个算法,确定一个字符串 s 的所有字符是否全都不同。
示例 1:
输入: s = “leetcode”
输出: false
示例 2:
输入: s = “abc”
输出: true
限制:
0 <= len(s) <= 100
如果你不使用额外的数据结构,会很加分。
package LeetCode._面试经典.笔记00;
import org.junit.Test;
public class _01_判断字符串是否唯一
public boolean isUnique01(String astr)
if (astr==null) return true;
if (astr.length()==0) return true;
int[] flag=new int[256];
char[] chars = astr.toCharArray();
boolean isU=true;
for (char aChar : chars)
if (flag[aChar]!=0) isU=false;
flag[aChar]++;
return isU;
/*
方法一样:不过用一个整数的位代表26(有限制26个小写字符)种字符
* */
public boolean isUnique(String astr)
if (astr==null) return true;
if (astr.length()==0) return true;
int flag=0;
for (int i=0;i<astr.length();i++)
if ((flag& 1<<(astr.charAt(i)-'a'))!=0) return false;
flag|=1<<(astr.charAt(i)-'a');
return true;
_02_判断是否互为字符重排
给定两个字符串 s1 和 s2,请编写一个程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。
示例 1:
输入: s1 = “abc”, s2 = “bca”
输出: true
示例 2:
输入: s1 = “abc”, s2 = “bad”
输出: false
说明:
0 <= len(s1) <= 100
0 <= len(s2) <= 100
package LeetCode._面试经典.笔记00;
public class _02_判断是否互为字符重排
//256辅助数组
public boolean CheckPermutation(String s1, String s2)
if (s1==null||s2==null) return false;
//长度不相等肯定不是
if (s1.length()==0&&s2.length()==0) return true;
if ((s1.length()^s2.length())!=0) return false;
int[] memory=new int[256];
char[] c1 = s1.toCharArray();
char[] c2 = s2.toCharArray();
for (int i=0;i<c1.length;i++)
memory[c1[i]]++;
memory[c2[i]]--;
for (int i : memory)
if (i!=0) return false;
return true;
_03_URL化
URL化。编写一种方法,将字符串中的空格全部替换为%20。假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的“真实”长度。(注:用Java实现的话,请使用字符数组实现,以便直接在数组上操作。)
示例 1:
输入:"Mr John Smith ", 13
输出:“Mr%20John%20Smith”
示例 2:
输入:" “, 5
输出:”%20%20%20%20%20"
提示:
字符串长度在 [0, 500000] 范围内。
package LeetCode._面试经典.笔记00;
import org.junit.Test;
import java.util.Arrays;
import java.util.HashMap;
public class _03_URL化
public String replaceSpaces01(String S, int length)
if (S==null) return null;
if (S.length()==0||S.length()<length) return "\\0";
char[] chars = S.toCharArray();
StringBuilder res=new StringBuilder();
for (int i=0;i<length;i++)
if (chars[i]==' ') res.append("%20");
else res.append(chars[i]);
return res.toString();
/*
另外一种时间空间效率更高的解法:先统计空格的个数
* */
public String replaceSpaces(String S, int length)
if (S==null) return null;
if (S.length()==0||S.length()<length) return "\\0";
char[] chars = S.toCharArray();
int countSP=0;
int i=0;
for (;i<length;i++)
if (chars[i]==' ') countSP++;
int len=length+countSP*2;
char[] res=new char[len];
i=0;
for (int j=0;j<len;)
if (chars[i]==' ')
res[j]='%';
res[j+1]='2';
res[j+2]='0';
j+=3;
else res[j++]=chars[i];
i++;
return new String(res);//字符数组转字符串正确方式是直接new
@Test
public void test()
new HashMap<>();
String s="Mr John Smith ";
String s1=replaceSpaces(s,13);
System.out.println(s1);
_04_回文序列
给定一个字符串,编写一个函数判定其是否为某个回文串的排列之一。
回文串是指正反两个方向都一样的单词或短语。排列是指字母的重新排列。
回文串不一定是字典当中的单词。
示例1:
输入:“tactcoa”
输出:true(排列有"tacocat"、“atcocta”,等等)
package LeetCode._面试经典.笔记00;
public class _04_回文序列
/*
首先应该询问面试官的是字符是ASCII字符还是Unicode统一编码字符
ASCII字符128个(拓展的ASCII码256个)
所有偶数长度的字符(不包括非字母字符)的字符必须出现偶数次;
所有奇数长度的字符的字符只能有一个出现奇数数次
归结为:1个回文串包含不超过1个奇数个的字符
优化:省略1次for循环,增加额外代码,但是此次优化却不一定就比原来的快
* */
public boolean canPermutePalindrome01(String s)
if (s==null) return false;
if (s.length()<=0) return true;
int[] res=new int[256];
char[] chars = s.toCharArray();
int times=0;
for (int i=0;i<chars.length;i++)
res[chars[i]]++;
if ((res[chars[i]]&1)==1) times++;
else times--;
/*
for (int i=0;i<256;i++)
if ((res[i]&1)==0) continue;
else times++;
*/
return times<=1;
/*
不采用数据结构:异或模拟开灯和关灯的操作,而不需要去管出现偶数次还是奇数次
在128位的字符中,如果是int(4字节=32比特)类型需要4位置(32*4=128),
但是如果用long(8字节=64比特)类型,只需要两位就行了,一个记录0-63,一个记录64-127
最后判断大于1的个数,如果大于1的话就不能构成回文序列
* */
public boolean canPermutePalindrome(String s)
if (s==null) return false;
if (s.length()<=0) return true;
long highBitmap=0;//64-127
long lowBitmap=0;//0-63
for (char c : s.toCharArray())
if (c>=64) highBitmap^=1l<<c-64;
else lowBitmap^=1l<<c;
return Long.bitCount(highBitmap)+Long.bitCount(lowBitmap)<=1;
_05_一次编辑
字符串有三种编辑操作:插入一个字符、删除一个字符或者替换一个字符。 给定两个字符串,编写一个函数判定它们是否只需要一次(或者零次)编辑。
示例 1:
输入:
first = “pale”
second = “ple”
输出: True
示例 2:
输入:
first = “pales”
second = “pal”
输出: False
package LeetCode._面试经典.笔记00;
public class _05_一次编辑
/*
首先思考替换,插入,删除的意义
替换:仅1位不同
插入:和删除相反
删除:除去1位后相同
长度大于1,false
替换
1)长度相同:找到第1个不同且后面要都相同
插入/删除
2)长度不同:找到第1个不同,短的那个等1位后面都要相同
时间复杂度:O(N) O(1)
* */
public boolean oneEditAway(String first, String second)
if (first==null||second==null) return false;
if (first.length()==0&&second.length()==0) return true;
int n1=first.length();
int n2=second.length();
int abs=n1-n2;
if (abs<-1||abs>1) return false;
/*String max=null;
String min=null;
if (n1>=n2)
max=first;
min=second;
else
max=second;
min=first;
int n=Math.max(n1,n2);
保持第一个最长:往回掉一次就够了
*/
if (n2>n1) return oneEditAway(second,first);
for (int i=0;i<n2;i++)
if (first.charAt(i)!=second.charAt(i))
//如果长度相同的字符串,那就比较下一个 都是i+1
if (n1==n2) return first.substring(i+1).equals(second.substring(i+1));
//如果长度不相同,那就从该字符开始比较 i+1 i
else return first.substring(i+1).equals(second.substring(i));
return true;//防止不进for循环,空和1个字符的情况
_06_字符串压缩
字符串压缩。利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。比如,字符串aabcccccaaa会变为a2b1c5a3。若“压缩”后的字符串没有变短,则返回原先的字符串。你可以假设字符串中只包含大小写英文字母(a至z)。
示例1:
输入:“aabcccccaaa”
输出:“a2b1c5a3”
示例2:
输入:“abbccd”
输出:“abbccd”
解释:“abbccd"压缩后为"a1b2c2d1”,比原字符串长度更长。
提示:
字符串长度在[0, 50000]范围内。
package LeetCode._面试经典.笔记00;
public class _06_字符串压缩
/*
双指针+StringBuilder O(N^2)
for循环内的字符串拷贝需要O(N)时间复杂度(流来处理,当然可能会快一些)
* */
public String compressString(String S)
if (S==null) return null;
if (S.length()==0) return S;
int n=S.length();
StringBuilder sb = new StringBuilder(n);//提前初始化容量,否则每次隐式扩容放2两倍浪费空间
int i=0,j=0;//首尾指针
while (j<n)
while (j<n&&S.charAt(j)==S.charAt(i)) j++;
sb.append(S.charAt(i));
sb.append(j-i);//j的位置已经是下一个字符了
i=j;
String res=sb.toString();
if (res.length()<S.length()) return res;
else return S;
_07_矩阵旋转
给你一幅由 N × N 矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 90 度。
不占用额外内存空间能否做到?
示例 1:
给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
示例 2:
给定 matrix =
[
[ 5, 1, 9,11],
[ 2, 4, 8,10],
[13, 3, 6, 7],
[15,14,12,16]
],
原地旋转输入矩阵,使其变为:
[
[15,13, 2, 5],
[14, 3, 4, 1],
[12, 6, 8, 9],
[16, 7,10,11]
]
package LeetCode._面试经典.笔记00;
import org.junit.Test;
public class _07_矩阵旋转
/*
要求:矩阵顺时针旋转
用辅助数组:对行一次旋转成列就能到正确的位置
主要理解2句话
1)第一行变成倒数第一列,
2)第一行的第x个元素变成倒数第一列的第x个元素。
matrix_new[j][n-1-i]=matrix[i][j];
不用辅助空间:
1.原地旋转 在上述方法的基础上考虑层次,而且每次只旋转4元素,其实就是上述的逆向思维
它去替换谁: matrix[j][n-1-i] = matrix[i][j]
||
V
谁来替换它: matrix[i][j]= matrix[n-1-j][i]
另外3个就一次类推了
matrix[n-1-j][i] = matrix[n-1-i][n-1-j]
matrix[n-1-i][n-1-j] = matrix[j][n-1-i]
matrix[j][n-1-i] = matrix[i][j]
2.翻转代替旋转
水平翻转:m[i][j]=>m[n-1-i][j]
对角线翻转:m[i][j]=>m[j][i]
m[i][j]=>m[n-1-i][j]=>m[j][n-1-i]
与上面的式子是一样的
* */
public void rotate01(int[][] matrix)
if (matrix==null) return;
int n=matrix.length;
for (int i=0;i<n/2;i++)//圈数控制
for (int j=i;j<n-1-i;j++)//每一圈每一行需要旋转的范围,最后一个别转
//倒着的顺时针
int temp=matrix[i][j];
matrix[i][j]= matrix[n-1-j][i];
matrix[n-1-j][i] = matrix[n-1-i][n-1-j];
matrix[n-1-i][n-1-j] = matrix[j][n-1-i];
matrix[j][n-1-i]=temp;
public void rotate(int[][] matrix)
if (matrix==null) return;
int n=matrix.length;
for (int i=0;i<n/2;i++)
for (int j=0;j<n;j++)
int temp=matrix[i][j];
matrix[i][j]=matrix[n-1-i][j];
matrix[n-1-i][j]=temp;
for (int i=0;i<n;i++)
以上是关于2021-6-12金典笔记00的主要内容,如果未能解决你的问题,请参考以下文章
算法 | 第2章 链表相关《程序员面试金典》#yyds干货盘点#