字符串、數組、鏈表、棧、二叉樹

1.1 字符串 肯定兩個字符串同構

StringA的字符從新排列後,可否變成StringB 詳細java

import java.util.*;

public class Same {
    public boolean checkSam(String stringA, String stringB) {
        // write code here
        if(stringA.length()!=stringB.length())
            return false;
        int[] recoder = new int[256];
        for(int i=0;i<stringA.length();i++){
            recoder[stringA.charAt(i)]++;
            recoder[stringB.charAt(i)]--;
        }
        for(int i=0;i<256;i++){
            if(recoder[i]!=0)
                return false;
        }
        return true;
    }
}

tips:node

  1. 第一步先判斷兩個字符串的長度是否相等數組

  2. 字符串的長度爲.length()有括號緩存

1.2 數組 清除二維數組行列

將數組中全部爲0的元素所在的行列都置爲0spa

import java.util.*;

public class Clearer {
    public int[][] clearZero(int[][] mat, int n) {
        // write code here
        boolean[] row = new boolean[n];
        boolean[] col = new boolean[n];
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(mat[i][j] == 0){
                    row[i] = true;
                    col[j] = true;
                }
            }
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(row[i]||col[j]){
                    mat[i][j]=0;
                }
            }
        }       
        return mat;
    }
}

tips指針

  • 讀數據和寫數據必須分開。code

1.3字符串 翻轉子串

檢查string2是否爲sting1旋轉而成對象

public boolean checkReverseEqual(String s1, String s2) {
        // write code here
        if (s1 == null || s2 == null || s1.length() != s2.length())
            return false;
        return (s1+s1).contains(s2);
    }

tips排序

  • 旋轉問題:先將string1 收尾拼接,再檢查新的字符串是否含有s2.遞歸

1.4鏈表 鏈表中倒數第k個結點

輸入一個鏈表,輸出該鏈表中倒數第k個結點

public ListNode FindKthToTail(ListNode head,int k) {
        //需不須要new???
        //ListNode headp = new ListNode(-1);
        if(head == null||k<1) return null;
        ListNode tailp = head;
        ListNode headp = head;
        for(int i=1;i<k;i++){
            tailp = tailp.next;
            if(tailp == null) return null;
        }
        while(tailp.next != null){
            tailp = tailp.next;
            headp = headp.next;
        }
        return headp;
    }

tips

  • new一個obj1對象,而後obj1 = obj2 ,錯錯錯

  • 核心思想:兩個指針,相差k-1,tail指到尾,則前指針正好找到想要的位置。

  • 另一種思路是採用遞歸,head==null時,將count置零,以後count++。

1.5鏈表 訪問單個節點的刪除

刪除單向鏈表中間的某個結點,而且只能訪問該結點

public boolean removeNode(ListNode pNode) {
        // write code here
        if(pNode == null || pNode.next == null)
            return false;
        pNode.val = pNode.next.val;
        pNode.next = pNode.next.next;
        return true;
    }

tips

  • 只能訪問該節點,則不能刪除該節點,由於刪除以後則鏈表與前面斷開連接,全部只能修改該節點的值爲下一節點的值,再指向下下節點。

1.6鏈表 鏈式A+B

鏈表頭爲個位,A{1,2,3},B{3,2,1},則返回{4,4,4}

public ListNode plusAB(ListNode a, ListNode b) {
        // write code here
        int flag = 0;
        ListNode result = new ListNode(-1);
        ListNode phead = result;
        while(a!=null || b!=null || flag!=0){
            int sum = flag;
            if(a!=null){
                sum+=a.val;
                a = a.next;
            }
            if(b!=null){
                sum+=b.val;
                b = b.next;
            }
            int val = sum%10;
            flag = sum/10;
            result.next = new ListNode(val);
            result = result.next;
        }
        return phead.next;
    }

tips

  • 以前有一個想法就是先相加公共部分,而後處理多出來的部分,這樣處理起來很是麻煩。

  • 若是鏈表頭爲高位,則採用棧方法處理。先對兩個鏈表分別壓棧,最後弾棧,直至兩個都爲空而且進位等於0。

1.7鏈表 迴文鏈表

檢查鏈表是否爲迴文,{1,2,3,2,1},返回true

public boolean isPalindrome(ListNode pHead) {
        // 快慢指針
        ListNode fast = pHead;
        ListNode slow = pHead;
        Stack<Integer> stack = new Stack<>();
        while(fast != null && fast.next != null){
            stack.push(slow.val);
            slow = slow.next;
            fast = fast.next.next;     
        }
        if(fast != null)
              slow = slow.next;
        while(slow != null){
            if(slow.val != stack.pop())
                return false;
            slow = slow.next;
        }
        return true;      
    }
    
    public boolean isPalindrome(ListNode pHead) {
        //雙棧
        if(pHead == null || pHead.next == null)
            return true;
        Stack stack1 = new Stack();        
        Stack stack2 = new Stack();

        while(pHead!=null){
            stack1.push(pHead.val);
            pHead = pHead.next;    
        }
        while(stack1.size()>stack2.size()){
            stack2.push(stack1.pop());
        }
        if(stack2.size()>stack1.size()){
            stack2.pop();
        }
        while(!stack1.empty() && !stack2.empty()){
            if(stack1.pop() != stack2.pop())
                return false;
        }
        return true;
            
    }

tips

  • 方案1:用快慢指針,當快指針指向鏈表尾部時,慢指針正好指向中部,而且將慢指針壓棧,這裏要注意奇偶數的區別。

  • 方案2:先將全部鏈表數據壓到棧1,而後彈出一半到棧2,二者再進行比較。不過該方法顯然沒有方法一效率高。

1.8棧和隊列 用兩個棧實現隊列

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
     
    public void push(int node) {
        stack1.push(node);
    }
     
    public int pop() {
        if(stack1.isEmpty() && stack2.isEmpty()){
            throw new RuntimeException("the queue is empty!");
        }
        if(stack2.isEmpty()){
          while(!stack1.isEmpty()){
              stack2.push(stack1.pop());
          }
        }
        return stack2.pop();
         
    }
}

tips

  • throw new RuntimeException("the queue is empty!");下次能夠用

1.9棧和隊列 雙棧排序

要求只有一個緩存棧,而且排好序的棧最大元素在棧頂。

public ArrayList<Integer> twoStacksSort(int[] numbers) {
        // write code here
        ArrayList<Integer> arrayList = new ArrayList();
        Stack<Integer> stack1 = new Stack();
        Stack<Integer> stack2 = new Stack();
         
        for(int i=0;i<numbers.length;i++){
            stack1.push(numbers[i]);
        }
         
        while(!stack1.isEmpty()){
            int temp = stack1.pop();
            while(!stack2.isEmpty() && stack2.peek()>temp){
                stack1.push(stack2.pop());
            }
            stack2.push(temp);
        }
         
        while(!stack2.isEmpty()){
            arrayList.add(stack2.pop());
        }
        return arrayList;
    }

tips

while(!stack2.isEmpty() && stack2.peek()>temp){
        stack1.push(stack2.pop());
     }
stack2.push(temp);
  • 代碼的簡潔性!思惟不要太僵硬,能夠多層條件一塊兒考慮,沒必要非要一層一層考慮分析。

  • 不要先考慮stack2是否爲空,再嵌套考慮棧頂是否大於temp。。。

2.0 樹 檢查二叉樹是否平衡

樹的平衡指左右高度相差不能大於1

public boolean isBalance(TreeNode root) {
        // 遍歷整個樹的全部節點
        if(root == null)return true;
        int left = getHeight(root.left);
        int right = getHeight(root.right);
        int cha = Math.abs(left-right);
        if(cha>1)return false;
        else return true;
    }
    public int getHeight(TreeNode root){
        if(root == null) return 0;
        int left = getHeight(root.left);
        int right = getHeight(root.right);
        return Math.max(left,right)+1;
    }
  • 另外一種解法:一邊檢查高度一邊檢查是否平衡

public boolean isBalance(TreeNode root) {
        // write code here
        if(root == null)return true;
        if(getHeight(root) == -1)return false;
        return true;
    }
    public int getHeight(TreeNode root){
        if(root == null) return 0;
        int left = getHeight(root.left);
        if(left == -1) return -1;
        int right = getHeight(root.right);
        if(right == -1) return -1;
        if(Math.abs(left-right)>1) return -1;
        else return Math.max(left,right)+1;
    }

tips

  • 這樣的改進的好處在於不用遍歷全部的樹節點

相關文章
相關標籤/搜索