劍指offer1-7題

/**

  • 在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。
    思路:
    選定一個維度(行或列)先找到需要查找的元素所在的行(列),再從該行(列)找到該元素的該元素具體的列(行)位置。複雜度O(n)。

優化:因爲數列是遞增有序的,可以進行二分查找進行優化,但是本題可以不進行二分也可以過。因爲大家有興趣可以去查一查編程語言數組可以開多大。然後單個查找在這個範圍內即使不優化也不會超時。有興趣的可以自己寫一寫二分!複雜度O(logn)
*/

public class Shuzuchazhao {


       public boolean Find(int target,int [][] array){
           if (array.length==0||array[0].length==0)
               return false;
           for (int i=array.length-1;i>=0;i--){
               if (array[i][0]>target){
                   continue;
               }
               for (int j=0;j<array[0].length;j++){
                    if (array[i][j] == target){
                        return true;
                    }
               }
           }
           return false;
       }
}

/**

  • 請實現一個函數,將一個字符串中的每個空格替換成“%20”。例如,當字符串爲We Are Happy.則經過替換之後的字符串爲We%20Are%20Happy。
  • 字符串遍歷重構即可。遇到爲 的字符直接在新的字符添加一個%20即可。當然,在java中直接使用replaceAll即可。複雜度O(n);
  • ps: replaceall效率較低,建議使用StringBuider之類完成
  • 大致就是 有討論是在原字符串上進行移動還是新建字符串的問題。當然新建字符串會更簡單些,但是如果遇到要求在原字符串基礎上進行移動的,因爲String的底層實現是數組,那就要首先遍歷一次知道有多少空格,然後擴充空間。至於遍歷完空格的移動方式:從後往前移動的方式更好,因爲最終移動的位置是相同的,但是從前往後每次遇到空格都會拖家帶口後面一串都要跟着移動。(好比國旗下講話排隊往後挫,要挫很多次整體慢慢騰騰移動),而從後往前插就相當於很明確一個個明確移動到哪。
  • 雖然兩者最終已經總距離一樣的,但是從前往後每個單詞要經過(1-n)次才能移動到最後,而從後往前每個單詞只1次就移動到目標位置!
    */
public class Tihuankongge {
       /** public static String replaceSpace(StringBuffer str){
            String team = str.toString();
            return team.replaceAll(" ","%20");
        }
        **/
        public static String  replaceSpace(StringBuffer str){
            StringBuffer str2=new StringBuffer();
             char demo=' ';
             for (int i=0;i<str.length();i++){
                 demo=str.charAt(i);
                 if (demo == ' '){
                     str2.append("%20");
                 }
                 else {
                     str2.append(demo);
                 }
             }
             return str2.toString();
        }
}

/**

  • 輸入一個鏈表,按鏈表從尾到頭的順序返回一個ArrayList。
  • 思路:
  • 題目給我們一個鏈表讓我們返回一個序列數字。而這個序列要求我們將鏈表從後向前的順序返回。當然,這樣的話處理方法就比較多了。比如先從前往後存到一個數組中,然後數組再從後往前往List中塞。
  • 當然Arraylist本身也是一個線性表(順序表),可以進行頭插。將鏈表每次向後遍歷的數插在首位,最後返回即可。
    */
public class Linkedlist {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {

        ArrayList<Integer>list=new ArrayList<Integer>();
        while (listNode!=null) {
            list.add(0, listNode.val);
            listNode=listNode.next;
        }
        return list;

    }
}

/**

  • 輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。
  • 我們都知道一箇中序序列帶着一個前序或者後序序列都能確定一棵完整的二叉樹。首先分析這種問題。二叉樹的問題大部分有可重複性,經常會使用遞歸。所以大部分人應該能夠想到使用遞歸,但是可能不清楚該怎麼遞歸。其實遞歸的使用不需要你考慮全篇,需要你謹慎完整的考慮其中一個過程。現在我們看看前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},的構造過程!
  • 對於前序,我們知道從根還是,所以可以確定第一個是根。然而中序是左中右。我們找到根的位置,那麼我們就可以確定這個根的左側是左側,根的右側是二叉樹的右側。
    
  • 然而很重要的一點是:在中序左側右側的在前序序列中的:根左右。雖然具體排序可能不同,但是左區域、右區域(區域元素總數量)也是連續的,所以我們這樣可以確定唯一一個根,然後前序有左右兩個區域,中序有左右兩個區域,這樣遞歸的構造子樹,知道完成二叉排序樹。
    
  • 所以,如果用代碼實現的話,比較麻煩的就是要考慮數組的區間問題,要記錄進行復原的兩數組的左右區間。
    

*/

public class Binarytree {

      public TreeNode reConstructBinaryTree(int [] pre, int [] in){
            TreeNode node=new TreeNode(in[0]);
            int preleft=0,preright=pre.length-1;
            int inleft=0,inright=pre.length-1;
            return creat(pre,in,preleft,preright,inleft,inright);
      }
      private TreeNode creat(int[] pre,int[] in,int preleft,int preright,int inleft,int inright){
            if (preleft>preright||inleft>inright) return null;
            TreeNode node=new TreeNode(pre[preleft]);
            int mid=0;
            for (int i=inleft;i<=inright;i++){
                  if (pre[preleft]==in[i]){
                        mid=i;
                  }
            }
            node.left=creat(pre,in,preleft+1,preleft+(mid-inleft),inleft,mid-1);
            node.right=creat(pre,in,preleft+(mid-inleft)+1,preright,mid+1,inright);
            return node;
      }
}

/**

  • 用兩個棧來實現一個隊列,完成隊列的Push和Pop操作。隊列中的元素爲int類型
  • 首先要了解隊列,隊列是一種先進先出(排隊)的結構,而棧是一種後進先出的結構。
  • 要求完成push和pop兩種操作。push就是加入隊尾(tail)類似enqueue,而pop是返回並拋出隊頭(front)類似dequeue。我們假設stack1是用作返回,而stack2用作中轉。可以先看看下面的圖。假設7、3、5、6在隊列中,待加入8(push8).
    */
public class Stack {

    java.util.Stack<Integer> stack1=new java.util.Stack<>();
    java.util.Stack<Integer> stack2=new java.util.Stack<>();

    public void push(int node){
        while (!stack1.isEmpty()){
            stack2.push(stack1.pop());
        }
        stack2.push(node);
        while (!stack2.isEmpty()){
            stack1.push(stack2.pop());
        }
        stack2.clear();
    }
    public int pop(){
        return stack1.pop();
    }
}

/**

  • 把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。
  • 輸入一個非遞減排序的數組的一個旋轉,輸出旋轉數組的最小元素。
  • 例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。
  • NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。
  • 思路:
  • 就是要求我們在這麼一組序列中找到最小的一個數字,非遞減的旋轉,也就是這麼一串有兩段非遞減的連續串串。找到第二個非遞減的串串頭就是結果。
  • 然而,我們只需第一次查找到最小即可結束。不會超時還是因爲數組大小有限制。無法提供更大量輸入數據。複雜度爲O(n);

*/

public class Xuanzhuanshuzu {
        public int minNumberInRotateArray(int[] array){
            if (array.length==0)return 0;
            int min=array[0];
            for (int i=0;i<array.length;i++){
                if (array[i]<min){
                    min=array[i];
                    break;
                }
            }
            return min;
        }

        int minNumberInRotateArray(vector<int> rotateArray){
            if (rotateArray.empty()){
                return 0;

                int low=0;
                int high=rotateArray.size()-1;
                int mid=0;

                while (low<high){
                    if (rotateArray[low] < rotateArray[high])
                        return rotateArray[low];
                    mid=low+(high-low)/2;
                    if (rotateArray[mid] > rotateArray[low])
                        low=mid+1;
                    else if (rotateArray[mid] < rotateArray[high])
                        high=mid;
                    else low++;
                }
                return rotateArray[low];
            }
        }
}

/**

  • 大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項(從0開始,第0項爲0)。
  • n<=39
    */
public class Feibona {

    public int Fibonacci(int n){
        if (n==1||n==0){
            return n;
        }else{
            return Fibonacci(n-1+Fibonacci(n-2));
        }
    }
    public int Fibonacci2(int n){
        int Fibo[]=new int[40];
        Fibo[0]=0;
        Fibo[1]=1;
        for (int i=2;i<=n;i++){
            Fibo[i]=Fibo[i-1]+Fibo[i-2];
        }
        return Fibo[n];
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章