《剑指offer》--二维数组中的查找、从头到尾打印链表、重建二叉树、旋转数组的最小数字
一、二維數值中的查找:
1、題目:
在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。
2、解題思路:
通過分析可以很簡單的找出一個規律,二維數組的最左下角的的點,該點的所在列上邊的點都是減少的,該點所在行右邊的點都是增加的。因此,我們以該點作為切入點,如果目標數比左下角的數大,則往右邊移動;如果目標數比左下角的數小,則往上邊移動;之后以此類推,如果匹配到目標數,則返回true;如果當移動到最右上角的點仍然沒有匹配到目標數,則返回false。
3、代碼示例:
public boolean Find(int target, int[][] array) {int rowCount = array.length;int colCount = array[0].length;int x, y;for (y = rowCount - 1, x = 0; y >= 0 && x < colCount;) {if (target == array[y][x]) {return true;} else if (target > array[y][x]) {x++;continue;} else if (target < array[y][x]) {y--;continue;}}return false;}?
二、從頭到尾打印鏈表:
1、題目:
輸入一個鏈表,按鏈表值從尾到頭的順序返回一個ArrayList。
2、代碼實現:
public class Solution{//第二種方式:遞歸實現:ArrayList<Integer> resultList = new ArrayList<Integer>();public ArrayList<Integer> printListFromTailToHead2(ListNode listNode) {if(listNode!=null){this.printListFromTailToHead2(listNode.next);resultList.add(listNode.val);}return resultList;}//第一種方式,使用堆棧結構public ArrayList<Integer> printListFromTailToHead1(ListNode listNode) {Stack<Integer> stack = new Stack<Integer>();while(listNode != null){stack.push(listNode.val);listNode = listNode.next;}ArrayList<Integer> resultList = new ArrayList<Integer>();while(!stack.isEmpty()){resultList.add(stack.pop());}return resultList;} }?
?
三、重建二叉樹:
1、題目:
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重復的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹并返回。
2、思路:
通過分析前序遍歷和中序遍歷的規律,前序遍歷的第一個節點就是二叉樹的根節點,中序遍歷中,位于根節點前面的所有節點都位于左子樹上,位于根節點后面的所有節點都位于右子樹上面。通過這個規律,我們可以使用遞歸方法來重建二叉樹。
3、代碼實現:
class TreeNode{int val;TreeNode left;TreeNode right;TreeNode(int x){val=x;} }public class Test1 {public TreeNode reConstructBinaryTree(int[] pre,int[] in){//前序的第一個數是根節點TreeNode root = new TreeNode(pre[0]);int len=pre.length;if(len==1){root.left=null;root.right=null;return root;}//找出中序中的根節點位置int rootVal=root.val;int i;for(i=0;i<len;i++){if(rootVal==in[i])break;}//構建左子樹if(i>0){int[] pr = new int[i];int[] ino = new int[i];for(int j=0;j<i;j++){pr[j]=pre[j+1];ino[j]=in[j];}root.left=reConstructBinaryTree(pr,ino);}else{root.left=null;}//構建右子樹if(len-i-1>0){int[] pr =new int[len-i-1];int[] ino = new int[len-i-1];for(int j=i+1;j<len;j++){pr[j-i-1]=pre[j];ino[j-i-1]=in[j];}root.right=reConstructBinaryTree(pr,ino);}else{root.right=null;}return root;}}4、第二種寫法:
public class Solution {public TreeNode reConstructBinaryTree(int [] pre,int [] in) {TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);return root;}//前序遍歷{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6}private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {if(startPre>endPre||startIn>endIn)return null;TreeNode root=new TreeNode(pre[startPre]);for(int i=startIn;i<=endIn;i++)if(in[i]==pre[startPre]){root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);break;}return root;} }?
四、旋轉數組的最小數字:
1、題目:
把一個數組最開始的若干個元素搬到數組的末尾,我們稱之為數組的旋轉。 輸入一個非減排序的數組的一個旋轉,輸出旋轉數組的最小元素。 例如數組{3,4,5,1,2}為{1,2,3,4,5}的一個旋轉,該數組的最小值為1。 NOTE:給出的所有元素都大于0,若數組大小為0,請返回0。
2、思路:
采用二分查詢的方法,但是需要處理兩種特殊情況:
即{1 0 1 1 1} 以及{1 1 1 0 1}這兩種類型的排序。
3、代碼實現:
public class Solution {public int minNumberInRotateArray(int [] array) {if(array.length==0){return 0;}int leftIndex=0;int rightIndex=array.length-1;int midIndex=0;while(array[leftIndex]>=array[rightIndex]){//當左右兩個指針相互接觸,則說明已經找到最小值,即右邊的指針的元素if(rightIndex-leftIndex<=1){midIndex=rightIndex;break;}midIndex=(leftIndex+rightIndex)/2;//這里是處理特殊情況,即當左中右三個指針的值都是一樣的時候,我們不能判斷最小元素位于哪個位置,只能通過遍歷的方法找出最小元素//特殊情況:{1 0 1 1 1} 以及{1 1 1 0 1}這兩種類型的排序if(array[rightIndex]==array[leftIndex] && array[leftIndex]==array[midIndex]){return MinInOrder(array,leftIndex,rightIndex);}//如果中間元素大于末尾元素,那么表明最小元素在后半段數組中,修改leftIndex指針位置if(array[midIndex]>=array[leftIndex]){leftIndex=midIndex;}else if(array[midIndex]<=array[rightIndex]){//如果中間元素小于末尾元素,那么表明最小元素在前半段部分中,修改rightIndex指針位置rightIndex=midIndex;}}return array[midIndex];}public int MinInOrder(int[] array,int leftIndex,int rightIndex){int result=array[leftIndex];for(int i=leftIndex+1;i<rightIndex;i++){if(result>array[i]){result=array[i];}}return result;}}4、代碼實現2:
public class Solution {public int minNumberInRotateArray(int [] array) {int low=0;int high = array.length-1;while(low<high){int mid = low + ((high - low) >> 2);if(array[mid] > array[high]){low = mid+1;}else if(array[mid] == array[high]){high--;}else{high =mid;}}return array[low];} }注意這里有個坑:如果待查詢的范圍最后只剩兩個數,那么mid 一定會指向下標靠前的數字
比如 array = [4,6]
array[low] = 4 ;array[mid] = 4 ; array[high] = 6 ;
如果high = mid - 1,就會產生錯誤, 因此high = mid
?
?
總結
以上是生活随笔為你收集整理的《剑指offer》--二维数组中的查找、从头到尾打印链表、重建二叉树、旋转数组的最小数字的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 二维矩阵中的最大矩形面积--java实现
 - 下一篇: 《剑指offer》-- 链表中倒数第k个