3. Longest Substring Without Repeating Characters
Code it now! https://leetcode.com/problems/longest-substring-without-repeating-characters/
问题描述:
必须是子串,而不是序列。
解题思路:
dp算法:时间复杂度O(n),空间复杂度O(n)。
本题用到了map作为重复元素位置的更新,用到了双指针,一个用来遍历String中的每个元素,另一个用来记录当前字符出现最新位置。dp递推公式为max=Math.max(max,i-j+1);代码如下:
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length() == 0) return 0;
HashMap<Character,Integer> map = new HashMap<Character,Integer>();
int max = 0;
//i指针用来遍历String,j指针用来记录重复出现元素的最新位置,用来更新位置。
for(int i=0,j=0;i<s.length();i++)
{
if(map.containsKey(s.charAt(i))){
//如果出现重复字符,j指针就会更新至遍历到i为止,没有出现重复字符的最右位置。 比如abba,j如果不取j和重复出现元素的最大值的话,当i=3时,j=0+1=1,最后计算出的最大子串长度就为3,因此还是要从j=2的位置算起。
j = Math.max(j,map.get(s.charAt(i))+1);
//j = map.get(s.charAt(i))+1; 错误!
}
map.put(s.charAt(i),i);
//动态规划方程。
max = Math.max(max,i-j+1);
}
return max;
}
}
17. Letter Combinations of a Phone Number
Code it now! https://leetcode.com/problems/letter-combinations-of-a-phone-number/
问题描述:
数字到字母映射如下。
解题思路:
回溯算法:时间复杂度O(2^n),空间复杂度O(1)。
本题使用了回溯思想分三步求解:1.针对问题,确定解空间(明确定义问题解空间)。
2.确定结点的子解终止条件。
3.一般以深度优先搜索解空间。
class Solution {
static String[] letterMap = {
" ", //0
"", //1
"abc", //2
"def", //3
"ghi", //4
"jkl", //5
"mno", //6
"pqrs", //7
"tuv", //8
"wxyz" //9
};
public static List<String> res = null;
public List<String> letterCombinations(String digits) {
//树形问题
res = new ArrayList<String>();
if(digits.equals("")){
return res;
}
//针对问题,确定解空间。
findCombination(digits,0,"");
return res;
}
//s中保存了从[0...index-1]翻译得到的一个字母字符串
//寻找和digits[index]匹配的字母,获得digits[0...index]翻译得到的解
public static void findCombination(String digits,int index,String s){
//2.确定结点的子解终止条件。
if(index==digits.length()){
res.add(s);
//此处则是已遍历完digits,因此不再进入下面的操作,而且需要return终止递归调用。
return ;
}
char c = digits.charAt(index);
String letters = letterMap[c-'0'];
//递归操作不断新添新元素至s当中。 这是组合问题,不需要回退一步。是找出所有组合 深度优先遍历
for(int i=0;i<letters.length();i++)
findCombination(digits,index+1,s+letters.charAt(i));
}
}
20. Valid Paraenttheses
Code it now! https://leetcode.com/problems/valid-parentheses/
问题描述:
解题思路:
dp算法:时间复杂度O(n),空间复杂度O(n)。
本题使用栈Stack来实现的括号匹配,思路是当遇到左括号({[时,进行压栈操作,当遇到右括号)}]时,进行出栈匹配操作,如果不能匹配返回false,全部都能匹配最后返回true,代码如下:
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<Character>();
for(int i=0;i<s.length();i++){
//遍历整个string,如果遇到左括号({[时,进行入栈操作。
if(s.charAt(i)=='('||s.charAt(i)=='{'||s.charAt(i)=='[')
stack.push(s.charAt(i));
else{
//如果遇到右括号)}]时,进行出栈匹配操作,首先判断栈是否为空,不为空进行match操作,最后判断是否成功配对。
if(stack.size()==0)
return false;
char c = stack.peek();
stack.pop();
char match;
if(s.charAt(i)==')'){
match = '(';
}else if(s.charAt(i)=='}'){
match = '{';
}else{
assert(s.charAt(i)==']');
match = '[';
}
if(c!=match){
return false;
}
}
}
if(stack.size()==0) return true;
else return false;
}
}
58. Length of Last Word
Code it now! https://leetcode.com/problems/length-of-last-word/
问题描述:
给定一个字符串由大写小写空格字符组成,返回字符串中最后一个单词长度,如果最后一个字符不存在则返回0。
解题思路:
String库函数算法:时间复杂度O(1),空间复杂度O(1)。
本题首先需要分析这个字符串,第一步是去除字符串前后的空格,第二步是找到最后一个空格的索引,第三步使用字符串总长度减去这个索引,即为最后一个单词的长度。代码如下:
class Solution {
public int lengthOfLastWord(String s) {
s = s.trim();
int lastIndex = s.lastIndexOf(' ') +1;
return s.length() - lastIndex;
}
}
67. Add Binary
Code it now! https://leetcode.com/problems/add-binary/
问题描述:
解题思路:
进位算法:时间复杂度O(n),空间复杂度O(1)或者O(n)。
本题可能大家一开始的想法是把两个二进制转换成十进制相加,然后再转为二进制输出结果。但是这里用到的是一种适合任何两个数相加的一种策略,在这简单的叫做进位法,从最右位数开始相加,该进位则进位的思想(这里需要注意的是进位的处理。使用到了count来统计进位)。代码如下:
class Solution {
public String addBinary(String a, String b) {
//第一步:把字符串转换成字符数组。
char[] c1 = a.toCharArray();
char[] c2 = b.toCharArray();
int len_a = a.length()-1;
int len_b = b.length()-1;
int index = 0;
StringBuffer sb = new StringBuffer();
while(len_a>=0||len_b>=0||index==1){
//判断是否走到了字符数组尽头,如果是则赋值0,不是则取出值。
int num1 = len_a>=0? c1[len_a]-'0':0;
int num2 = len_b>=0? c2[len_b]-'0':0;
int count = num1+num2;
//此处分三种情况讨论,见判断条件。
if(count+index==3){
index = 1;
sb.append(1);
}else if(count+index==2){
index = 1;
sb.append(0);
}else{
sb.append(count+index);
index = 0;
}
len_a--;
len_b--;
}
return sb.reverse().toString();
}
}
344. Reverse String
Code it now! https://leetcode.com/problems/reverse-string/
问题描述:
解题思路:
StringBuilder库函数算法:时间复杂度O(1),空间复杂度O(1)。
String中没有对字符串反转的库方法,但是StringBuilder提供了丰富的库方法,此处主要利用到库函数去处理问题。简单代码如下:
class Solution {
public String reverseString(String s) {
StringBuffer sb = new StringBuffer();
sb.append(s);
return sb.reverse().toString();
}
}
如果不使用库方法,我们又是如何实现的字符串反转呢? 下面的方法实现在leetcode中显示超时。。。
class Solution {
public String reverseString(String s) {
String str = "";
for(int i=s.length()-1;i>=0;i--)
{
str += s.charAt(i);
}
return str;
}
}
于是对比,可以发现stringbuilder反转实现比这个好。str+这个操作很消耗时间。进一步又想到了采用双指针的方式去反转这个字符串。代码如下:
class Solution {
public String reverseString(String s) {
char[] c = s.toCharArray();
int i = 0;
int j = s.length()-1;
while(i<j)
{
char temp = c[i];
c[i] = c[j];
c[j] = temp;
i++;
j--;
}
return new String(c);
}
}