14. Longest Common Prefix
本题注意用反向判断
String s=new String();
char c;
for(int i=0;i<strs[0].length();i++){
c=strs[0].charAt(i);
for(int j=0;j<strs.length;j++){
if(strs[j].length()<=i||strs[j].charAt(i)!=c)//反向判断
return s;
}
s+=Character.toString(c);
}
return strs[0];
17. Letter Combinations of a Phone Number
这道题网上都说用dfs,其实,没有用dfs,用的就是递归的想法。
class Solution {
public List<String> letterCombinations(String digits) {
String[] s={"","1","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
LinkedList<String> l=new LinkedList<String>();
if(digits.length()==0)
return l;//注意要判断一下为空的情况
String curr="";
int index=0;
dfs(digits,index,curr,s,l);
return l;
}
public void dfs(String digits,int index,String curr,String[] s,LinkedList<String> l){
if(index==digits.length()){
l.add(curr);
return ;
}
int n=Character.getNumericValue(digits.charAt(index));
for(int i=0;i<s[n].length();i++){
String temp =curr;
curr+=s[n].charAt(i);
dfs(digits,index+1,curr,s,l);
curr=temp;
}
}
}
19. Remove Nth Node From End of List
这道题,可以只遍历一次,用两个相隔n的指针就可以了,我的代码遍历了两次,因为只用了一次指针
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode curr=head;
if(curr.next==null&&n==1)
return null;
LinkedList<ListNode> l=new LinkedList<ListNode>();
while(curr!=null){
l.push(curr);
curr=curr.next;
}
ListNode par=curr;
for(int i=0;i<n;i++){
curr=l.pop();
}
if(l.isEmpty()){
head=curr.next;
curr.next=null;
}
else{
par=l.pop();
par.next=curr.next;
curr.next=null;
}
return head;
}
}
20. Valid Parentheses
这道题,我不知道第一种方法哪里错了,我在自己电脑上运行时,结果正确,我猜测是不满足空间复杂度的要求
方法一
class Solution {
public boolean isValid(String s) {
if(s.length()==0)
return false;
int l=0,m=0,b=0;
for(int i=0;i<s.length();i++){
if(l<0||m<0||b<0)
return false;
char c=s.charAt(i);
n:switch(c){
case '(':
l++;
break n;
case ')':
l--;
break n;
case '[':
m++;
break n;
case ']':
m--;
break n;
case '{':
b++;
break n;
case '}':
b--;
break n;
}
}
return l==0&&m==0&&b==0;
}
}
方法二
class Solution {
public boolean isValid(String s) {
if(s==null)
return false;
HashMap<Character,Character> h=new HashMap<Character,Character>();
h.put('{','}');
h.put('[',']');
h.put('(',')');
LinkedList<Character> l=new LinkedList<Character>();
for(int i=0;i<s.length();i++){
if(s.charAt(i)=='('||s.charAt(i)=='['||s.charAt(i)=='{')
l.push(s.charAt(i));
else if(!l.isEmpty()&&s.charAt(i)==h.get(l.pop()))
continue;
else
return false;
}
return l.isEmpty();
}
21. Merge Two Sorted Lists
一定要注意在对链表做操作时,注意cur.next=new ListNode(x),分清楚情况,不能直接对null的赋值,cur必须要先有才能赋值,一定注意!
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode l=new ListNode(0);
ListNode curr=l;
while(l1!=null&&l2!=null){
if(l1.val<l2.val){
curr.next=new ListNode(l1.val);
l1=l1.next;
}
else{
curr.next=new ListNode(l2.val);
l2=l2.next;
}
curr=curr.next;
}
if(l1!=null)
curr.next=l1;
if(l2!=null)
curr.next=l2;
return l.next;
}
}
22. Generate Parentheses
错误示范
class Solution {
public List<String> generateParenthesis(int n) {
List<String> l=new ArrayList<String>();
if(n==0)
return l;
String curr="";
int open=0;
int close=0;
backTracking(l,curr,open,close,n);
return l;
}
public void backTracking(List<String> l,String curr,int open,int close,int max){
if(curr.length()==max*2){
l.add(curr);
return;
}
if(open<max){
curr+="(";//不应加上这个,应该在递归回溯的时候加上,因为如果不合适的话,它将回
溯到上一层
backTracking(l,curr,open+1,close,max);
}
if(close<open){
curr+=")";
backTracking(l,curr,open,close+1,max);
}
}
}
正确代码
class Solution {
public List<String> generateParenthesis(int n) {
List<String> l=new ArrayList<String>();
if(n==0)
return l;
String curr="";
int open=0;
int close=0;
backTracking(l,curr,open,close,n);
return l;
}
public void backTracking(List<String> l,String curr,int open,int close,int max){
if(curr.length()==max*2){
l.add(curr);
return;
}
if(open<max){
backTracking(l,curr+"(",open+1,close,max);
}
if(close<open){
curr+=")";
backTracking(l,curr+")",open,close+1,max);
}
}
}
23. Merge k Sorted Lists
这道题主要利用的就是之前说过的归并排序,利用分治法和数组融合
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists.length==0) return null;
return sort(lists,0,lists.length-1);
}
public ListNode merge(ListNode l1,ListNode l2){
ListNode l=new ListNode(0);
ListNode cur=l;
while(l1!=null&&l2!=null){
if(l1.val<l2.val){
cur.next=new ListNode(l1.val);
l1=l1.next;
}
else{
cur.next=new ListNode(l2.val);
l2=l2.next;
}
cur=cur.next;
}
while(l1!=null){
cur.next=new ListNode(l1.val);
l1=l1.next;
cur=cur.next;
}
while(l2!=null){
cur.next=new ListNode(l2.val);
l2=l2.next;
cur=cur.next;
}
return l.next;
}
public ListNode sort(ListNode[] lists,int start,int end){
if(start==end)
return lists[start];
else{
ListNode left=sort(lists,start,(start+end)/2);
ListNode right=sort(lists,(start+end)/2+1,end);
return merge(left,right);
}
}
}
25. Reverse Nodes in k-Group
上图代表一次k链表反转,root,node,head代表的是什么
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode root=new ListNode(-1);
ListNode res=root;
root.next=head;
int i=0;
ListNode temp=head;
//计算整个链表节点数,存在i中
while(temp!=null){
temp=temp.next;
i++;
}
while(i>=k){//为了使最后一个不足k个节点的链表部分不进行反转,使i每经过一次k链表的反转后减k
for(int j=0;j<k-1;j++){
//用head当k中的反转后的最后一个,node代表root下一个,head代表k中末尾节点,root代表k节点的前一个节点,只有node每次不同,root和head在一次k链表反转中是不变的
ListNode node=root.next;
root.next=head.next;
head.next=root.next.next;
root.next.next=node;
}
root=head;
head=root.next;
i-=k;
}
return res.next;
}
}
26. Remove Duplicates from Sorted Array
class Solution {
public int removeDuplicates(int[] nums) {
int i=0,j=0;
int k=1;
while(i<nums.length-1){
n:while(j<nums.length){
if(nums[i]==nums[j])
j++;
else{
k++;
nums[i+1]=nums[j];
break n;
}
}
i++;
}
return k;
}
}
27. Remove Element
class Solution {
public int removeElement(int[] nums, int val) {
Arrays.sort(nums);
int i=0,j=nums.length-1,k=0;
if(nums.length==0)
return 0;
while(i<=j){ //一定注意这块有等号
if(nums[i]==val){
if(nums[j]!=val){
nums[i++]=nums[j--];
k++;
}
else j--;
}
else{
i++;
k++;
}
}
return k;
}
}
29. Divide Two Integers
这道题注意:1)其实溢出就只有一种情况,在代码第一个if考虑就可以了,
2)long和int转换,一定要将dividend和divisor转换成long
3)注意两个while循环,采用的是二分法。
class Solution {
public int divide(int dividend, int divisor) {
if(dividend ==Integer.MIN_VALUE&& divisor == -1)
return Integer.MAX_VALUE;
if(dividend==0||divisor==0)
return 0;
boolean sign=true;
if((dividend<0&&divisor>0)||(dividend>0&&divisor<0))
sign=false;
long a=Math.abs((long)dividend);
long b=Math.abs((long)divisor);
if(a<b)
return 0;
long result=0;
long sum=0;
long pow=0;
while(a>=b){
sum = b;
pow = 1;
while(sum+sum<=a){
sum+=sum;
pow+=pow;
}
a-=sum;
result+=pow;
}
return sign==true?(int)result:(int)-result;
}
}
30. Substring with Concatenation of All Words
这道题主要思想:就是利用两个HashMap存储每个单词,一个存储words里的单词及其出现的次数,另一存储在搜索字符串s中出现的单词及其次数,两个哈希表里所对应的单词(key)的value一样的话,就匹配成功。注意HashMap更新映射时的用到的方法,还有它只有containsKey和containsValue的用法,没有contains的用法。
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> res=new ArrayList<Integer>();
int wordsNum=words.length;
if(wordsNum==0)
return res;
int wordLen=words[0].length();
HashMap<String,Integer> h1=new HashMap<String,Integer>();
for(int i=0;i<words.length;i++){
h1.put(words[i],h1.getOrDefault(words[i],0)+1);
}
for(int i=0;i<=s.length()-wordLen*wordsNum;i++){
int num=0;
HashMap<String,Integer> h2=new HashMap<String,Integer>();
n:while(num<wordsNum){
String word=s.substring(i+num*wordLen,i+(num+1)*wordLen);
if(h1.containsKey(word)){
h2.put(word,h2.getOrDefault(word,0)+1);
if(h2.get(word)>h1.get(word))
break n;
}
else
break n;
num++;
}
if(num==wordsNum)//num和wordsNum不一定一样,一样才算匹配成功
res.add(i);
}
return res;
}
}