1.二維數組中的查找
題目描述:在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。
誤區:以斜對角的數組為比較對象,並不是大於array[i][i],小於array[i+1][i+1]的數字還很多很多;滿足這個條件只能排除左上角的一小塊。
1 //思路:矩陣是有序的,從左下角來看,向上數字遞減,向右數字遞增,因此從左下角開始查找,當要查找數字比左下角數字大時。右移要查找數字比左下角數字小時,上移。 2 class Solution { 3 public: 4 bool Find(vector<vector<int> > array,int target) { 5 int rowCount = array.size(); 6 int colCount = array[0].size(); 7 int i,j; 8 for(i=rowCount-1,j=0;i>=0&&j<colCount;){ 9 if(target == array[i][j]) 10 return true; 11 if(target < array[i][j]){ 12 i--; 13 continue; 14 } 15 if(target > array[i][j]){ 16 j++; 17 continue; 18 } 19 } 20 return false; 21 } 22 };
2.替換空格
題目描述:請實現一個函數,將一個字符串中的每個空格替換成“%20”。例如,當字符串為We Are Happy.則經過替換之后的字符串為We%20Are%20Happy。
誤區:用循環時,注意到每替換一個空格,字符串的長度都會增加。所以循環必定不能遍歷新的字符串。
1 public class Solution { 2 public String replaceSpace(StringBuffer str) { 3 int l=str.length(); 4 for(int i=0;i<l;i++){ 5 if(str.charAt(i)==' ') 6 str.replace(i, i+1, "%20"); 7 } 8 return str.toString(); 9 } 10 }
1 //新建一個字符串,在后面疊加。但是這個方法並不是在原有數組上進行改動。 2 public class Solution { 3 public String replaceSpace(StringBuffer str) { 4 int l=str.length(); 5 String ans=""; 6 for(int i=0;i<l;i++){ 7 if(str.charAt(i)==' ') 8 ans+="%20"; 9 else 10 ans+=str.charAt(i); 11 } 12 return ans; 13 } 14 } 15 16 //這個就比較投機了 17 public class Solution { 18 public static String replaceSpace(StringBuffer str) { 19 String str1=str.toString(); 20 String str2=str1.replace(" ","%20"); 21 return str2; 22 23 } 24 }
3.從尾到頭打印鏈表
題目描述:輸入一個鏈表,按鏈表值從尾到頭的順序返回一個ArrayList
誤區:當java中new了一個對象之后,這個實例就不等於null了,就已經分配內存了;返回的時候不要返回null,會報空指針異常,要用return new ArrayList<>();
1 //這段代碼超時了 2 public ArrayList<Integer> printListFromTailToHead(ListNode listNode) { 3 ArrayList<Integer> ans=new ArrayList<>(); 4 if(listNode==null) 5 return new ArrayList<>(); 6 else if(listNode.next==null){ 7 ans.add(listNode.val); 8 return ans; 9 } 10 ListNode head=listNode; 11 ListNode temphead=listNode; 12 ListNode first=null,second=null; 13 while(listNode.next!=null){ 14 first=listNode; 15 second=listNode.next; 16 listNode=listNode.next; 17 } 18 while(true){ 19 ans.add(second.val); 20 ans.add(first.val); 21 if(first==head) 22 break; 23 second=first; 24 while(temphead.next!=null){ 25 if(temphead.next==first) 26 first=temphead; 27 } 28 temphead=listNode; 29 } 30 return ans; 31 } 32 33 //這段用了一個數據結構:棧,很簡單 34 public ArrayList<Integer> printListFromTailToHead(ListNode listNode) { 35 ArrayList<Integer> ans=new ArrayList<>(); 36 if(listNode==null) 37 return new ArrayList<>(); 38 39 Stack<Integer> temp=new Stack<>(); 40 while(listNode!=null){ 41 temp.push(listNode.val); 42 listNode=listNode.next; 43 } 44 while(!temp.empty()){ 45 ans.add(temp.pop()); 46 } 47 return ans; 48 } 49 50 //這段用了兩個arraylist,一個前向一個逆向 51 public ArrayList<Integer> printListFromTailToHead(ListNode listNode) { 52 ArrayList<Integer> list = new ArrayList<Integer>(); 53 ArrayList<Integer> result = new ArrayList<Integer>(); 54 ListNode temp = listNode; 55 while ( temp != null ) { 56 list.add( temp.val ); 57 temp = temp.next; 58 } 59 for ( int i = list.size()-1; i>=0; i-- ) { 60 result.add( list.get(i) ); 61 } 62 return result; 63 }
4.重建二叉樹(中等題)
題目描述:輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重復的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。
注意點:遞歸傳入的參數要仔細斟酌
1 public TreeNode reConstructBinaryTree(int [] pre,int [] in) { 2 if(pre==null || in==null || pre.length!=in.length) 3 return null; 4 return help(pre,in,0,pre.length-1,0,in.length-1); 5 } 6 public TreeNode help(int [] pre,int [] in,int startpre,int endpre,int startin,int endin){ 7 if(startin>endin || startpre>endpre) 8 return null; 9 int root=pre[startpre]; 10 int i=0; 11 for(i=startin;i<=endin;i++){ 12 if(in[i]==root) 13 break; 14 } 15 TreeNode ans=new TreeNode(root); 16 ans.left=help(pre,in,startpre+1,startpre+i-startin,startin,i-1); 17 ans.right=help(pre,in,startpre+i-startin+1,endpre,i+1,endin); 18 return ans; 19 }
5.反轉鏈表
題目描述:輸入一個鏈表,反轉鏈表后,輸出新鏈表的表頭。
誤區:是在原鏈表的基礎上反轉,盡量不要借助外部存儲結構
/* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } }*/ public class Solution { public ListNode ReverseList(ListNode head) { ListNode cur=head; ListNode pre=null; ListNode next=null; while(cur!=null){ next=cur.next; cur.next=pre; pre=cur; cur=next; } return pre; } }
6.合並兩個排序的鏈表
題目描述:輸入兩個單調遞增的鏈表,輸出兩個鏈表合成后的鏈表,當然我們需要合成后的鏈表滿足單調不減規則。
誤區:用遞歸會比較簡單;鏈表題要注意空指針異常和最后要返回頭指針
//遞歸 鏈接:https://www.nowcoder.com/questionTerminal/d8b6b4358f774294a89de2a6ac4d9337 來源:牛客網 public ListNode Merge(ListNode list1,ListNode list2) { if(list1 == null){ return list2; } if(list2 == null){ return list1; } if(list1.val <= list2.val){ list1.next = Merge(list1.next, list2); return list1; }else{ list2.next = Merge(list1, list2.next); return list2; } } //非遞歸 public ListNode Merge(ListNode list1,ListNode list2) { ListNode temp1=list1; ListNode temp2=list2; while(temp2 != null){ //System.out.println(temp1.val); //System.out.println(); if (temp2.val >= temp1.val && temp1.next != null && temp2.val <= temp1.next.val ) { ListNode node = new ListNode(temp2.val); node.next = temp1.next; temp1.next = node; temp1 = temp1.next; temp2 = temp2.next; } else if (temp2.val < temp1.val) { ListNode node = new ListNode(temp2.val); node.next = temp1; temp1 = node; temp2 = temp2.next; } else if (temp2.val >= temp1.val && temp1.next==null) { ListNode node = new ListNode(temp2.val); temp1.next = node; temp1=temp1.next; temp2 = temp2.next; } else temp1 = temp1.next; } return list1; }
7.鏈表中倒數第k個結點
題目描述:輸入一個鏈表,輸出該鏈表中倒數第k個結點。
誤區:在java中,判斷一個數據結構是否為空,需要與null比較,!=或者==
1 public class Solution {//復雜度為2n-k 2 public ListNode FindKthToTail(ListNode head,int k) { 3 if(!head) 4 return null; 5 int n=0; 6 ListNode listnode=new ListNode(0); 7 listnode=head; 8 while(listnode){ 9 listnode=listnode.next; 10 n++; 11 } 12 if(k>n) 13 return null; 14 for(int i=0;i<n-k;i++){ 15 head=head.next; 16 } 17 return head; 18 } 19 } 20 21 22 public class Solution {//復雜度為n 23 public ListNode FindKthToTail(ListNode head,int k) { 24 if(head==null||k<=0){ 25 return null; 26 } 27 ListNode pre=head; 28 ListNode last=head; 29 for(int i=1;i<k;i++){ 30 if(pre.next!=null){ 31 pre=pre.next; 32 }else{ 33 return null; 34 } 35 } 36 while(pre.next!=null){ 37 pre = pre.next; 38 last=last.next; 39 } 40 return last; 41 } 42 }
8.樹的子結構
題目描述:輸入兩棵二叉樹A,B,判斷B是不是A的子結構。(ps:我們約定空樹不是任意一個樹的子結構)
誤區:子結構的題,要想着從大的樹每個結點出發,然后遍歷小的樹,看看能不能遍歷完全
1 public class Solution { 2 public boolean HasSubtree(TreeNode root1,TreeNode root2){ 3 if(root1==null || root2==null) 4 return false; 5 else 6 return help(root1,root2) || help(root1.left,root2) || help(root1.right,root2); 7 } 8 9 public boolean help(TreeNode root1,TreeNode root2){ 10 if(root2==null) 11 return true; 12 if(root1==null) 13 return false; 14 if(root1.val==root2.val) 15 return help(root1.left,root2.left) && help(root1.right,root2.right); 16 else 17 return false; 18 } 19 }
9.順時針打印矩陣(中等題)
題目描述:輸入一個矩陣,按照從外向里以順時針的順序依次打印出每一個數字,例如,如果輸入如下4 X 4矩陣: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 則依次打印出數字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
誤區:邊界條件很重要,看這篇博客https://blog.csdn.net/weixin_37672169/article/details/80207479
import java.util.ArrayList; public class Solution { public ArrayList<Integer> printMatrix(int [][] matrix) { ArrayList<Integer> list = new ArrayList<Integer>(); int rows = matrix.length; int cols = matrix[0].length; if(matrix == null || cols <= 0 || rows <= 0){ return null; } int start = 0; while(cols > start*2 && rows > start*2){ printMatrixInCircle(list, matrix, cols, rows, start); ++start; } return list; } private void printMatrixInCircle(ArrayList<Integer> list, int[][] nums, int cols, int rows, int start) { int endX = cols - 1 - start; int endY = rows - 1 - start; //從左到右打印一行 for (int i = start; i <= endX; ++i) { int number = nums[start][i]; list.add(number); } //從上到下打印一列 if(start < endY){ for (int i = start + 1; i <= endY; ++i) { int number = nums[i][endX]; list.add(number); } } //從右向左打印一行 if(start < endX && start < endY){ for (int i = endX-1; i >= start; --i) { int number = nums[endY][i]; list.add(number); } } //從下向上打印一列 if(start < endX && start < endY - 1){ for (int i = endY-1; i >= start + 1; --i) { int number = nums[i][start]; list.add(number); } } } }
10.棧的壓入、彈出序列
題目描述:輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否可能為該棧的彈出順序。假設壓入棧的所有數字均不相等。例如序列1,2,3,4,5是某棧的壓入順序,序列4,5,3,2,1是該壓棧序列對應的一個彈出序列,但4,3,5,1,2就不可能是該壓棧序列的彈出序列。(注意:這兩個序列的長度是相等的)
誤區:要模擬棧
import java.util.Stack; public class Solution { public boolean IsPopOrder(int [] pushA,int [] popA) { if(pushA.length==0) return false; Stack<Integer> stack=new Stack<Integer> (); for(int i=0,j=0;i<pushA.length;i++){ stack.push(pushA[i]); while(j < pushA.length && stack.peek() == popA[j]){ stack.pop(); j++; } } return stack.empty(); } }
11.二叉搜索樹的后序遍歷序列
題目描述:輸入一個整數數組,判斷該數組是不是某二叉搜索樹的后序遍歷的結果。如果是則輸出Yes,否則輸出No。假設輸入的數組的任意兩個數字都互不相同。
誤區:當有多個情況需要考慮的時候,並行可以轉化成串行
public class Solution { public boolean VerifySquenceOfBST(int [] sequence) { int len=sequence.length; if(len==0) return false; return help(sequence,0,len-1); } boolean help(int [] sequence,int start,int end){ if(start>=end) return true; int i=end; while(i > start && sequence[i-1] > sequence[end]) i--; for(int j=i-1;j>=start;j--){ if(sequence[j]>sequence[end]) return false; } return help(sequence,start,i-1) && help(sequence,i,end-1); } }
12.機器人的運動范圍
題目描述:地上有一個m行和n列的方格。一個機器人從坐標0,0的格子開始移動,每一次只能向左,右,上,下四個方向移動一格,但是不能進入行坐標和列坐標的數位之和大於k的格子。 例如,當k為18時,機器人能夠進入方格(35,37),因為3+5+3+7 = 18。但是,它不能進入方格(35,38),因為3+5+3+8 = 19。請問該機器人能夠達到多少個格子?。
誤區:要注意優化,不然會超時。第二部分是學長的並查集解法,暫時沒看懂。
public class Solution { int ans=0; public int movingCount(int threshold, int rows, int cols){ int [][]nums=new int[rows+5][cols+5]; help(0,0,threshold,rows, cols,nums); return ans; } private void help(int i,int j,int threshold,int rows, int cols,int [][]nums){ if(i>rows-1 || j>cols-1 || !check(i,j,threshold)) return; if(nums[i][j]==0){ ans++; nums[i][j]=1; help(i+1,j, threshold, rows, cols, nums); help(i,j+1, threshold, rows, cols, nums); } } private boolean check(int i,int j,int threshold){ int ans=0; while(i>0){ ans+=i%10; i=(i-(i%10))/10; } while(j>0){ ans+=j%10; j=(j-(j%10))/10; } //System.out.println(ans); return ans<=threshold; } public static void main(String [] args){ Solution s=new Solution(); System.out.println(s.movingCount(5,10,10)); } } public class Solution2 { public int movingCount(int threshold, int rows, int cols) { if (threshold < 0) return 0; int[] board = new int[rows * cols]; setBoard(board, cols, threshold); UnionFind uf = new UnionFind(rows * cols); for (int i = 0; i < rows * cols; i++) { int row = i / cols; int col = i % cols; if (board[i] == 1) { if (col + 1 < cols && board[row * cols + col + 1] == 1) uf.union(i, row * cols + col + 1); if (row + 1 < rows && board[(row + 1) * cols + col] == 1) uf.union(i, (row + 1) * cols + col); } } return uf.getCount(); } private void setBoard(int[] board, int cols, int threshold) { for (int i = 0; i < board.length; i++) { int row = i / cols; int col = i % cols; if (getSum(row) + getSum(col) <= threshold) { board[i] = 1; } } } private int getSum(int i) { int sum = 0; while (i != 0) { sum += i % 10; i = i / 10; } return sum; } class UnionFind { private int count = 1; private int[] parent; UnionFind(int n) { parent = new int[n]; for (int i = 0; i < n; i++) { parent[i] = i; } } int getCount() { return count; } int find(int i) { if (parent[i] != i) { parent[i] = find(parent[i]); } return parent[i]; } void union(int i, int j) { int pi = find(i); int pj = find(j); if (pi == pj) return; int pos = find(0); if (pi == pos || pj == pos) { parent[pi] = pj; count++; } } } }
13.復雜鏈表的復制(中等題)
題目描述:輸入一個復雜鏈表(每個節點中有節點值,以及兩個指針,一個指向下一個節點,另一個特殊指針指向任意一個節點),返回結果為復制后復雜鏈表的head。(注意,輸出結果中請不要返回參數中的節點引用,否則判題程序會直接返回空)。
誤區:這道題的解決方法是散步,1.將每個結點的數值進行復制,賦給新的結點,把新的結點插在相應的結點后面;2.依次復制每個結點的隨機指針;3.分離。要注意的是,原鏈表的結構不能改變,不然通不過,所以最后還有一個還原的操作
1 public class Solution { 2 public RandomListNode Clone(RandomListNode pHead) { 3 if(pHead==null) 4 return null; 5 6 RandomListNode head=pHead; 7 while(head!=null){ 8 RandomListNode temp=new RandomListNode(head.label); 9 temp.next=head.next; 10 head.next=temp; 11 head=head.next.next; 12 } 13 14 RandomListNode head2=pHead; 15 while(head2!=null){ 16 head2.next.random=head2.random==null?null:head2.random.next; 17 head2=head2.next.next; 18 } 19 20 RandomListNode head3=pHead.next; 21 RandomListNode newhead=pHead.next; 22 RandomListNode head4=pHead; 23 while(head3.next!=null){ 24 RandomListNode temp=head3.next; 25 head3.next=head3.next.next; 26 head4.next=temp; 27 head3=head3.next; 28 head4=head4.next; 29 } 30 head4.next=null; 31 return newhead; 32 33 } 34 }
14.二叉搜索樹與雙向鏈表
題目描述:輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。要求不能創建任何新的結點,只能調整樹中結點指針的指向。
誤區:
1 /** 2 public class TreeNode { 3 int val = 0; 4 TreeNode left = null; 5 TreeNode right = null; 6 7 public TreeNode(int val) { 8 this.val = val; 9 10 } 11 12 } 13 */ 14 15 16 public class Solution { 17 TreeNode head = null; 18 TreeNode realHead = null; 19 public TreeNode Convert(TreeNode pRootOfTree) { 20 ConvertSub(pRootOfTree); 21 return realHead; 22 } 23 24 private void ConvertSub(TreeNode pRootOfTree) { 25 if(pRootOfTree==null) return; 26 ConvertSub(pRootOfTree.left); 27 if (head == null) { 28 head = pRootOfTree; 29 realHead = pRootOfTree; 30 } else { 31 head.right = pRootOfTree; 32 pRootOfTree.left = head; 33 head = pRootOfTree; 34 } 35 ConvertSub(pRootOfTree.right); 36 } 37 }
15.數組中出現次數超過一半的數字
題目描述:數組中有一個數字出現的次數超過數組長度的一半,請找出這個數字。例如輸入一個長度為9的數組{1,2,3,2,2,2,5,4,2}。由於數字2在數組中出現了5次,超過數組長度的一半,因此輸出2。如果不存在則輸出0。
誤區:這道題如果用hash就很簡單,難的是怎么找空間復雜度為常數的方法,這里推薦“陣地攻守的思想”:第一個數字作為第一個士兵,守陣地;count = 1;遇到相同元素,count++;遇到不相同元素,即為敵人,同歸於盡,count--;當遇到count為0的情況,又以新的i值作為守陣地的士兵,繼續下去,到最后還留在陣地上的士兵,有可能是主元素。再加一次循環,記錄這個士兵的個數看是否大於數組一般即可。
1 package hash; 2 3 import java.util.HashMap; 4 //數組中出現次數超過一半的數字 5 6 //別人的思路:采用陣地攻守的思想: 7 //第一個數字作為第一個士兵,守陣地;count = 1; 8 //遇到相同元素,count++; 9 //遇到不相同元素,即為敵人,同歸於盡,count--;當遇到count為0的情況,又以新的i值作為守陣地的士兵,繼續下去,到最后還留在陣地上的士兵,有可能是主元素。 10 //再加一次循環,記錄這個士兵的個數看是否大於數組一般即可。 11 public class Solution2 { 12 public int MoreThanHalfNum_Solution(int [] array) { 13 int len=array.length; 14 HashMap<Integer,Integer> hash=new HashMap<>(); 15 for(int i=0;i<len;i++){ 16 17 if(hash.get(array[i])==null) 18 hash.put(array[i],1); 19 else{ 20 21 hash.put(array[i],hash.get(array[i])+1); 22 } 23 if(hash.get(array[i])>len/2) 24 return array[i]; 25 } 26 return 0; 27 } 28 29 public int MoreThanHalfNum_Solution2(int [] array) { 30 int flag=array[0]; 31 int count=1; 32 int nums=0; 33 for(int i=1;i<array.length;i++){ 34 if(array[i]==flag) 35 count++; 36 else 37 count--; 38 if(count==0) { 39 flag = array[i]; 40 count++; 41 } 42 } 43 for(int i=0;i<array.length;i++){ 44 if(array[i]==flag) 45 nums++; 46 } 47 if(nums>array.length/2) 48 return flag; 49 return 0; 50 51 } 52 53 }
16.最小的k個數
題目描述:輸入n個整數,找出其中最小的K個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,。
誤區:這道題第一個想法是hash,也比較簡單,但是空間復雜度不定。網上常用方法是最大堆和分治。
1 package 最大堆; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 import java.util.TreeSet; 6 //最小的K個數 7 public class Solution { 8 public static ArrayList<Integer> getLeastNumbers(int []nums, int k) { 9 ArrayList<Integer> list = new ArrayList<Integer>(); 10 int lens = nums.length; 11 if (nums == null || lens == 0 || k > lens || k <= 0) { 12 return list; 13 } 14 TreeSet<Integer> kSet = new TreeSet<Integer>(); 15 for (int i = 0; i < lens; i++) { 16 if (kSet.size() < k) { 17 kSet.add(nums[i]); 18 } else if (nums[i] < kSet.last()) { 19 kSet.remove(kSet.last()); 20 kSet.add(nums[i]); 21 } 22 } 23 Iterator<Integer> iterator = kSet.iterator(); 24 while (iterator.hasNext()) { 25 list.add(iterator.next()); 26 } 27 return list; 28 } 29 }
17.矩陣中的路徑
題目描述:請設計一個函數,用來判斷在一個矩陣中是否存在一條包含某字符串所有字符的路徑。路徑可以從矩陣中的任意一個格子開始,每一步可以在矩陣中向左,向右,向上,向下移動一個格子。如果一條路徑經過了矩陣中的某一個格子,則之后不能再次進入這個格子。 例如 a b c e s f c s a d e e 這樣的3 X 4 矩陣中包含一條字符串"bcced"的路徑,但是矩陣中不包含"abcb"路徑,因為字符串的第一個字符b占據了矩陣中的第一行第二個格子之后,路徑不能再次進入該格子。。
誤區:如何把代碼寫的簡潔美觀是很重要的一點
1 package shensou; 2 3 //矩陣中的路徑 4 public class Solution { 5 public boolean hasPath(char[] matrix, int rows, int cols, char[] str) { 6 int flag[] = new int[matrix.length]; 7 for (int i = 0; i < rows; i++) { 8 for (int j = 0; j < cols; j++) { 9 if (helper(matrix, rows, cols, i, j, str, 0, flag)) 10 return true; 11 } 12 } 13 return false; 14 } 15 16 private boolean helper(char[] matrix, int rows, int cols, int i, int j, char[] str, int k, int[] flag) { 17 int index = i * cols + j; 18 if (i < 0 || i >= rows || j < 0 || j >= cols || matrix[index] != str[k] || flag[index] == 1) 19 return false; 20 if(k == str.length - 1) return true; 21 flag[index] = 1; 22 if (helper(matrix, rows, cols, i - 1, j, str, k + 1, flag) 23 || helper(matrix, rows, cols, i + 1, j, str, k + 1, flag) 24 || helper(matrix, rows, cols, i, j - 1, str, k + 1, flag) 25 || helper(matrix, rows, cols, i, j + 1, str, k + 1, flag)) { 26 return true; 27 } 28 flag[index] = 0; 29 return false; 30 } 31 32 boolean ans=false; 33 public boolean hasPath(char[] matrix, int rows, int cols, char[] str){ 34 int len=matrix.length; 35 boolean [] flag=new boolean[len]; 36 if(len==0) 37 return false; 38 for(int i=0;i<len;i++){ 39 help(matrix,i,str,0,rows,cols,flag); 40 System.out.println("yuanxu"); 41 if(ans) 42 return true; 43 } 44 return false; 45 } 46 void help2(char[] matrix, int i, char[] str,int index,int rows,int cols,boolean []flag){ 47 48 if(i>=matrix.length || i<0 || flag[i] || matrix[i]!=str[index]) 49 return; 50 if(matrix[i]==str[index] && index==str.length-1){ 51 ans=true; 52 return; 53 } 54 55 flag[i]=true; 56 System.out.print("i: "); 57 System.out.print(i); 58 System.out.println(matrix[i]); 59 if(i%cols==0) { 60 help(matrix,i+cols,str,index+1,rows,cols,flag); 61 if(ans) 62 return; 63 help(matrix,i-cols,str,index+1,rows,cols,flag); 64 if(ans) 65 return; 66 help(matrix,i+1,str,index+1,rows,cols,flag); 67 if(ans) 68 return; 69 } 70 71 else if(i%cols==cols-1){ 72 help(matrix,i+cols,str,index+1,rows,cols,flag); 73 if(ans) 74 return; 75 help(matrix,i-cols,str,index+1,rows,cols,flag); 76 if(ans) 77 return; 78 help(matrix,i-1,str,index+1,rows,cols,flag); 79 if(ans) 80 return; 81 } 82 83 else{ 84 help(matrix,i+1,str,index+1,rows,cols,flag); 85 if(ans) 86 return; 87 help(matrix,i-1,str,index+1,rows,cols,flag); 88 if(ans) 89 return; 90 help(matrix,i+cols,str,index+1,rows,cols,flag); 91 if(ans) 92 return; 93 help(matrix,i-cols,str,index+1,rows,cols,flag); 94 if(ans) 95 return; 96 } 97 flag[i]=false; 98 99 100 }
18.求1+2+3+...+n
題目描述:求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句(A?B:C)。
誤區:想不到
1 public class Solution { 2 public int Sum_Solution(int n) { 3 int ans=n; 4 boolean a=(ans>0) && ((ans+=Sum_Solution(n-1))>0); 5 return ans; 6 7 } 8 }
19.和為S的連續正數序列
題目描述:小明很喜歡數學,有一天他在做數學作業時,要求計算出9~16的和,他馬上就寫出了正確答案是100。但是他並不滿足於此,他在想究竟有多少種連續的正數序列的和為100(至少包括兩個數)。沒多久,他就得到另一組連續正數和為100的序列:18,19,20,21,22。現在把問題交給你,你能不能也很快的找出所有和為S的連續正數序列? Good Luck!
誤區:用滑動窗口的思想,做過了就會做了
1 import java.util.ArrayList; 2 public class Solution { 3 public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { 4 if(sum<=0) 5 return new ArrayList<>(); 6 ArrayList<ArrayList<Integer>> ans=new ArrayList<>(); 7 8 int low=1,high=2; 9 10 while(high>low){ 11 int num=(low+high)*(high-low+1)/2; 12 if(num==sum){ 13 ArrayList<Integer> temp=new ArrayList<>(); 14 for(int i=low;i<=high;i++) 15 temp.add(i); 16 ans.add(temp); 17 low++; 18 } 19 else if(num<sum) 20 high++; 21 else 22 low++; 23 } 24 return ans; 25 } 26 }
20.和為S的兩個數字
題目描述:輸入一個遞增排序的數組和一個數字S,在數組中查找兩個數,使得他們的和正好是S,如果有多對數字的和等於S,輸出兩個數的乘積最小的。
誤區:當兩個數和相同時,越靠近乘積越大
1 import java.util.ArrayList; 2 3 public class Solution { 4 public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) { 5 int len=array.length; 6 if(len<=1) 7 return new ArrayList<>(); 8 ArrayList<Integer> ans=new ArrayList<>(); 9 int i=0; 10 int j=len-1; 11 while(i<j){ 12 if (array[i] + array[j]<sum) 13 i++; 14 else if(array[i] + array[j]>sum) 15 j--; 16 else{ 17 ans.add(array[i]); 18 ans.add(array[j]); 19 break; 20 21 } 22 } 23 24 25 return ans; 26 27 } 28 }
21.左旋轉字符串
題目描述:匯編語言中有一種移位指令叫做循環左移(ROL),現在有個簡單的任務,就是用字符串模擬這個指令的運算結果。對於一個給定的字符序列S,請你把其循環左移K位后的序列輸出。例如,字符序列S=”abcXYZdef”,要求輸出循環左移3位后的結果,即“XYZdefabc”。是不是很簡單?OK,搞定它!
誤區:如果左移的不是字符串而是數組,就要三次反轉來做
1 class Solution { 2 public: 3 string LeftRotateString(string str, int n) 4 { 5 int len = str.size(); 6 if(len == 0) return str; 7 n %= len; 8 for(int i = 0, j = n - 1; i < j; ++i, --j) swap(str[i], str[j]); 9 for(int i = n, j = len - 1; i < j; ++i, --j) swap(str[i], str[j]); 10 for(int i = 0, j = len - 1; i < j; ++i, --j) swap(str[i], str[j]); 11 return str; 12 } 13 }; 14 15 public class Solution { 16 public String LeftRotateString(String str,int n) { 17 18 String ans=""; 19 return ans = (str.length()==0) ? "" : str.substring(n%str.length(),str.length()).concat(str.substring(0,n%str.length())); 20 21 } 22 }
22.撲克牌順子
題目描述:LL今天心情特別好,因為他去買了一副撲克牌,發現里面居然有2個大王,2個小王(一副牌原本是54張^_^)...他隨機從中抽出了5張牌,想測測自己的手氣,看看能不能抽到順子,如果抽到的話,他決定去買體育彩票,嘿嘿!!“紅心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是順子.....LL不高興了,他想了想,決定大\小 王可以看成任何數字,並且A看作1,J為11,Q為12,K為13。上面的5張牌就可以變成“1,2,3,4,5”(大小王分別看作2和4),“So Lucky!”。LL決定去買體育彩票啦。 現在,要求你使用這幅牌模擬上面的過程,然后告訴我們LL的運氣如何, 如果牌能組成順子就輸出true,否則就輸出false。為了方便起見,你可以認為大小王是0。
誤區:有沒有一種方法可以不排序
1 import java.util.Arrays; 2 3 public class Solution { 4 public boolean isContinuous(int [] numbers) { 5 Arrays.sort(numbers); 6 int temp=0; 7 for(int i=0;i<numbers.length-1;i++){ 8 if(numbers[i]!=0){ 9 if(numbers[i+1]==numbers[i]) 10 return false; 11 else 12 temp=temp+numbers[i+1]-numbers[i]; 13 } 14 } 15 return temp+1<=numbers.length; 16 } 17 }
23.數字在排序數組中出現的次數
題目描述:統計一個數字在排序數組中出現的次數。
誤區:兩次二分,一次找開頭,一次找結尾
1 public class Solution { 2 public int GetNumberOfK(int[] array,int k){ 3 if(array==null||array.length==0) 4 return 0; 5 int first=getFirstK(array,k,0,array.length-1); 6 int last=getLastK(array,k,0,array.length-1); 7 if(first==-1 ||last==-1){ 8 return 0; 9 } 10 else{ 11 return last-first+1; 12 } 13 14 } 15 16 public int getFirstK(int[] array,int k,int start,int end){ 17 while(start<=end){ 18 int mid=(start+end)/2; 19 if(k<array[mid]) 20 end=mid-1; 21 else if(k>array[mid]) 22 start=mid+1; 23 else{ 24 if((mid>0&&array[mid-1]!=k)||mid==0) 25 return mid; 26 else{ 27 end=mid-1; 28 } 29 } 30 } 31 return -1; 32 } 33 34 public int getLastK(int[] array,int k ,int start,int end){ 35 while(start<=end){ 36 int mid=(start+end)/2; 37 if(k<array[mid]) 38 end=mid-1; 39 else if(k>array[mid]) 40 start=mid+1; 41 else{ 42 if((mid<array.length-1&&array[mid+1]!=k)||mid==array.length-1) 43 return mid; 44 else{ 45 start=mid+1; 46 } 47 } 48 } 49 return -1; 50 } 51 }
24.平衡二叉樹
題目描述:輸入一棵二叉樹,判斷該二叉樹是否是平衡二叉樹。
誤區:遞歸,代碼要寫的好看。從最底下開始
1 //重復計算的代碼 2 public classSolution { 3 public boolean IsBalanced_Solution(TreeNode root) { 4 if(root == null) { 5 return true; 6 } 7 return Math.abs(maxDepth(root.left) - maxDepth(root.right)) <= 1 && 8 IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right); 9 } 10 11 private int maxDepth(TreeNode root) { 12 if(root == null) { 13 return 0; 14 } 15 return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)); 16 } 17 } 18 19 20 //不重復計算的代碼 21 public class Solution { 22 public boolean IsBalanced_Solution(TreeNode root) { 23 return getDepth(root) != -1; 24 } 25 26 private int getDepth(TreeNode root) { 27 if (root == null) return 0; 28 int left = getDepth(root.left); 29 if (left == -1) return -1; 30 int right = getDepth(root.right); 31 if (right == -1) return -1; 32 return Math.abs(left - right) > 1 ? -1 : 1 + Math.max(left, right); 33 } 34 }
25.數組中只出現一次的數字
題目描述:一個整型數組里除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。
誤區:第一檔是遍歷,第二檔是hash,第三檔是位運算
1 import java.util.Arrays; 2 import java.util.HashMap; 3 import java.util.HashSet; 4 import java.util.Set; 5 6 public class Solution { 7 public void FindNumsAppearOnce2(int [] array,int num1[] , int num2[]) { 8 if(array.length>1){ 9 Arrays.sort(array); 10 int i=1; 11 int flag=0; 12 while(i<array.length){ 13 if(array[i]==array[i-1]){ 14 if(i+2>=array.length){ 15 num2[0]=array[i+1]; 16 break; 17 } 18 else 19 i+=2; 20 } 21 22 else{ 23 if(flag==0){ 24 if(i==array.length-1){ 25 num1[0]=array[i-1]; 26 num2[0]=array[i]; 27 break; 28 } 29 num1[0]=array[i-1]; 30 flag++; 31 } 32 else{ 33 num2[0]=array[i-1]; 34 break; 35 } 36 i++; 37 } 38 39 } 40 } 41 42 } 43 44 public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) { 45 Set<Integer> hm=new HashSet<>(); 46 for(int i=0;i<array.length;i++){ 47 if(hm.contains(array[i])) 48 hm.remove(array[i]); 49 else 50 hm.add(array[i]); 51 } 52 int []temp={0,0}; 53 int j=0; 54 for(int i :hm){ 55 temp[j]=i; 56 j++; 57 } 58 num1[0]=temp[0]; 59 num2[0]=temp[1]; 60 61 } 62 }
26.把數組排成最小的數
題目描述:輸入一個正整數數組,把數組里所有數字拼接起來排成一個數,打印能拼接出的所有數字中最小的一個。例如輸入數組{3,32,321},則打印出這三個數字能排成的最小數字為321323。
誤區:自定義比較器很奇妙
1 package 數組; 2 3 import java.util.ArrayList; 4 import java.util.Collections; 5 import java.util.Comparator; 6 7 public class Solution { 8 public String PrintMinNumber(int [] numbers) { 9 int n; 10 String s=""; 11 ArrayList<Integer> list= new ArrayList<Integer>(); 12 n=numbers.length; 13 for(int i=0;i<n;i++){ 14 list.add(numbers[i]); 15 16 } 17 list.sort(new Comparator<Integer>() { 18 19 public int compare(Integer str1, Integer str2) { 20 String s1 = str1 + "" + str2; 21 String s2 = str2 + "" + str1; 22 return s1.compareTo(s2); 23 } 24 }); 25 26 for(int j:list){ 27 s+=j; 28 } 29 return s; 30 31 } 32 }
27.把字符串轉換成整數
題目描述:將一個字符串轉換成一個整數(實現Integer.valueOf(string)的功能,但是string不符合數字要求時返回0),要求不能使用字符串轉換整數的庫函數。 數值為0或者字符串不是一個合法的數值則返回0。
誤區:溢出判斷
1 public class Solution { 2 public int StrToInt(String str) { 3 if(str.length()==0) 4 return 0; 5 int ans=0; 6 int flag=0; 7 if(str.charAt(0)=='-') 8 flag=-1; 9 else 10 flag=1; 11 12 for(int i=0;i<str.length();i++){ 13 if(i==0 && ((str.charAt(i)=='+' || str.charAt(i)=='-'))) 14 continue; 15 else if(str.charAt(i)>='0' && str.charAt(i)<='9'){ 16 int temp=ans; 17 ans=ans*10+(str.charAt(i)-'0'); 18 if((temp-(str.charAt(i)-'0')/10!=ans))//溢出判斷 19 return 0; 20 21 } 22 23 else 24 return 0; 25 } 26 return ans*flag; 27 28 } 29 30 public static void main(String[] args) { 31 Solution s=new Solution(); 32 int a=s.StrToInt("2147483648"); 33 System.out.println(a); 34 } 35 }
8.反轉鏈表
題目描述:輸入一個鏈表,反轉鏈表后,輸出新鏈表的表頭。
誤區:是在原鏈表的基礎上反轉,盡量不要借助外部存儲結構
