【算法】算法進階

文章目錄

1.整數

1.1判斷一個數是不是迴文數

public boolean isPalindrome(int x) {
    if (x<0 || (x!=0 && x%10==0)) return false;
    int rev = 0;
    while (x>rev){
    	rev = rev*10 + x%10;
    	x = x/10;
    }
    return (x==rev || x==rev/10);
}

1.2LeetCode231. Power of Two(判斷一個數是不是2的n次冪)

class Solution {
    public boolean isPowerOfTwo(int n) {
        return (n > 0) && ((n & (n-1)) == 0);
    }
}

1.3整數中1出現的次數,即從1到n整數中1出現的次數(劍指Offer)

求出113的整數中1出現的次數,並算出1001300的整數中1出現的次數?爲此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數。

public class Solution {
    public int NumberOf1Between1AndN_Solution(int n) {
       int count=0;
       StringBuilder link=new StringBuilder();
       for(int i=0;i<n+1;i++)
           link.append(i);
       String test=link.toString();
       for(int j=0;j<test.length();j++)
           {
           if(test.charAt(j)=='1')    //這裏是最需要注意的地方
               count++;
            }
       return count;
       }
}

2.數組

2.1LeetCode27 Remove Element

Given an array and a value, remove all instances of that value in place and return the new length.
Do not allocate extra space for another array, you must do this in place with constant memory.
The order of elements can be changed. It doesn’t matter what you leave beyond the new length.

Example:
Given input array nums = [3,2,2,3], val = 3
Your function should return length = 2, with the first two elements of nums being 2.
解答:


public class Solution {
    public int removeElement(int[] nums, int val) {
        int m=0;
        for(int j=0;j<nums.length;j++){
            if(nums[j]!=val){
                nums[m]=nums[j];
                m++;
       }}
        return m;
    }
}

2.2連續子數組的最大和(劍指Offer)

一個整數數組中的元素有正有負,在該數組中找出一個連續子數組,要求該連續子數組中各元素的和最大,這個連續子數組便被稱作最大連續子數組。

public class Solution {  
    public int FindGreatestSumOfSubArray(int[] array) {  
        if(array.length==0)  
            return 0;  
        int temp=array[0];                        
        int sum=array[0];                       //這個sum一定要是array[0],爲了防止數組全是負數  
        for(int i=1;i<array.length;i++)         //注意這個i的起始值是1  
            {  
            if(temp>0)  temp=temp+array[i];     //如果前一段和>0,保留temp  
            else  
            temp=array[i];                      //如果前一段和<0,捨棄temp  
            if(temp>sum)  
            sum=temp;  
            }  
        return sum;  
    }  

2.3數組中只出現一次的數字

一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。

//num1,num2分別爲長度爲1的數組。傳出參數
//將num1[0],num2[0]設置爲返回結果
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        int match=0;
        int flag=1;
        if(array.length<2)
            return;
        for(int i=0;i<array.length;i++){
            match^=array[i];
        } 
        //如果有兩個數字不相同,那麼肯定macth有一位是1,然後通過while找到那個1 進行分組!
        while((match&flag)==0) flag<<=1;    //找到那個1
        for(int j=0;j<array.length;j++)
        {
            if((flag&array[j])==0) num1[0]^=array[j];
                else 
                   num2[0]^=array[j];      
        }       
    }
}

2.4LeetCode217 Contains Duplicate(判斷數組是否包含重複值)

Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.


public class Solution {  
    public boolean containsDuplicate(int[] nums) {  
        Set<Integer> a=new HashSet<Integer>();  
       for(int i:nums){  
           if(!a.add(i))  
        return true;  
       }  
        return false;  
    }  
} 

2.5第一個只出現一次的字符

在一個字符串(1<=字符串長度<=10000,全部由字母組成)中找到第一個只出現一次的字符,並返回它的位置

import java.util.*;
 
public class Solution {
        public int FirstNotRepeatingChar(String str) {
                Map<Character, Integer> map = new HashMap<Character, Integer>();
        for(int i=0;i<str.length();i++){
            if(map.containsKey(str.charAt(i))){
                int time = map.get(str.charAt(i));
                map.put(str.charAt(i), ++time);
            }
            else {
                map.put(str.charAt(i), 1);
            }
        }
        for(int i=0;i<str.length();i++){
            char c = str.charAt(i);
            if (map.get(c) == 1) {
                return i;
            }
        }
        return -1;
       }
}

2.6Remove Duplicates from Sorted Array

Given a sorted array, remove the duplicates in-place such that each element appear only once and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.


Given nums = [1,1,2],
 
Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.
It doesn't matter what you leave beyond the new length.

解答:


public int removeDuplicates(int[] nums) {
    int cur = 0 ; 
    for(int n:nums)
        if(n>nums[cur])
            nums[++cur] = n;
    return cur+1;
}

2.7LeetCode238 Product of Array Except Self(數組元素除它自身之外的乘積)

Given an array nums of n integers where n > 1, return an array out such that output[i] is equal to the product of all the elements of nums except nums[i]

Input:  [1,2,3,4]
Output: [24,12,8,6]

Note: Please solve it without division and in O(n).
解題思路:

先遍歷數組左邊的相乘,然後再乘以右邊的。


class Solution {
    public int[] productExceptSelf(int[] nums) {
        int n = nums.length;
        int [] result = new int[n];
        result[0] = 1;
        for (int i = 1; i < n; i++){
            result[i] = result[i -1] * nums[i - 1];   
        }
        int right = 1;
        for (int i = n - 1; i >= 0; i--){   //注意邊界
            result[i] = result[i] * right;
            right = right * nums[i];      
        }
        return result;
    }
}

3.鏈表

3.1倒數第k個節點(劍指Offer)

/* 
public class ListNode { 
    int val; 
    ListNode next = null; 
 
    ListNode(int val) { 
        this.val = val; 
    } 
}*/  
public class Solution {  
    public ListNode FindKthToTail(ListNode head,int k) {     
      if(head==null||k==0)  
          return null;                              //防止鏈表是空   或者倒數第0個結點  
      ListNode p1=head;                             //倒數越界  
      ListNode p2=head;                               
      int i=1;  
      while(i<k){                                        //從1個節點去第k個節點,就是往前走k-1步  
          if(p1.next==null)                              //主要是防止K大於了鏈表的長度,p1.next是空,說明將要越界了。  
              return null;  
          p1=p1.next;  
          i++;  
      }  
      while(p1.next!=null){  
          p1=p1.next;  
          p2=p2.next;  
      }  
      return p2;  
      }  
}  

這個題的思路是設立兩個結點,讓第一個先走到k節點,然後兩個節點同時往後走,當第一個結點走到最後一個結點時,第二個正好走到倒數第K個節點。

3.2LeetCode83 Remove Duplicates from Sorted List(刪除排序鏈表中的重複元素)

Given a sorted linked list, delete all duplicates such that each element appear only once.

For example,
Given 1->1->2, return 1->2.

Given 1->1->2->3->3, return 1->2->3.

注意:這裏是排序好的!
解答:

/** 
 * Definition for singly-linked list. 
 * public class ListNode { 
 *     int val; 
 *     ListNode next; 
 *     ListNode(int x) { val = x; } 
 * } 
 */  
  
class Solution {  
    public ListNode deleteDuplicates(ListNode head) {  
        if(head==null||head.next==null)  
         return head;                     //     如果鏈表爲空或只有一個節點,返回null或這個節點就可以  
        ListNode temp=head;                        
        while(temp.next!=null){           //     如果當前結點的下一個節點不爲空,比較當前結點和下一個結點  
        if(temp.next.val==temp.val)  
            temp.next=temp.next.next;     //     如果當前結點和下一個結點相同,直接將下一個節點改爲下下結點  
        else  
            temp=temp.next;               //     如果不同,繼續往後  
        }  
        return head;  
    }  
}  

3.3LeetCode82 Remove Duplicates from Sorted List II(刪除排序鏈表的重複元素2)

Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.

For example,
Given 1->2->3->3->4->4->5, return 1->2->5.
Given 1->1->1->2->3, return 2->3

解答:

class Solution {  
    public ListNode deleteDuplicates(ListNode head) {  
            if (head == null) return null;  
      
    if (head.next != null && head.val == head.next.val) {              //如果當前結點和他下一結點相等         
        while (head.next != null && head.val == head.next.val) {         
            head = head.next;                                          //head一直往後  
        }  
        return deleteDuplicates(head.next);                            //把這一段的捨去,然後判斷剩下的  
    } else {  
        head.next = deleteDuplicates(head.next);                       //如果不相等保留,從下一個結點繼續判斷  
    }  
    return head;                                                         
    }  
}  

3.4約瑟夫環(程序員面試金典)

約瑟夫問題是一個非常著名的趣題,即由n個人坐成一圈,按順時針由1開始給他們編號。然後由第一個人開始報數,數到m的人出局。現在需要求的是最後一個出局的人的編號。

給定兩個int n和m,代表遊戲的人數。請返回最後一個出局的人的編號。保證n和m小於等於1000。

import java.util.*;  
public class Joseph {  
    public int getResult(int n, int m) {  
      
        LinkedList<Integer> test=new LinkedList<Integer>();   //注意鏈表初始化,別忘了()  
        for (int i=1;i<=n;i++)  
        {test.add(i);}  
        int start=0;  
        while(test.size()>1){                                 //注意鏈表長度取法  
            int need=(start+m-1)%test.size();  
            test.remove(need);  
            start=need%test.size();  
            }  
            return test.get(0);  
    }  
 }      

3.5LeetCode203. Remove Linked List Elements(移除鏈表元素)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        while(head != null && head.val == val) {
            head = head.next;
        }
        if(head == null)
            return head;
        ListNode temp = head;
        while(temp.next != null){
            if(temp.next.val == val){
            temp.next = temp.next.next;}
            else{
            temp = temp.next;}
        }
        return head;
    }
}

4.二叉樹

4.1LeetCode104 Maximum Depth of Binary Tree(求二叉樹的最大深度)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public int maxDepth(TreeNode root) {
       if(root==null) return 0;
       int  left=maxDepth(root.left);
       int  right=maxDepth(root.right);
       return 1+Math.max(left,right);
    }
}

4.2LeetCode111 Minimum Depth of Binary Tree(求二叉樹的最小深度)

**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public int minDepth(TreeNode root) {
        if(root==null) return 0;
        int left=minDepth(root.left);
        int right=minDepth(root.right);
        return (left==0||right==0)?left+right+1:Math.min(left,right)+1;    
}
}

注意防止斜樹

4.3等價二叉樹(劍指Offer)

/** 
 * Definition of TreeNode: 
 * public class TreeNode { 
 *     public int val; 
 *     public TreeNode left, right; 
 *     public TreeNode(int val) { 
 *         this.val = val; 
 *         this.left = this.right = null; 
 *     } 
 * } 
 */  
  
  
public class Solution {  
    /* 
     * @param a: the root of binary tree a. 
     * @param b: the root of binary tree b. 
     * @return: true if they are identical, or false. 
     */  
    public boolean isIdentical(TreeNode a, TreeNode b) {  
        // write your code here  
        if(a==null&&b==null)  return true;  
        if(a==null||b==null)  return false;  
        if(a.val==b.val) return isIdentical(a.left,b.left)&&isIdentical(a.right,b.right);  
        else  
        return false;  
          
          
    }  
}  

4.4LeetCode404 Sum of Left Leaves(左葉子節點和)

    3
   / \
  9  20
    /  \
   15   7
 
There are two left leaves in the binary tree, with values 9 and 15 respectively. Return 24.
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        int sum=0;
        if(root==null)                  
            return 0;
        if(root.left!=null)
        {
            if((root.left.left==null)&&(root.left.right==null)){
                sum=sum+root.left.val;
            }else
            sum=sum+sumOfLeftLeaves(root.left);
        }
        sum=sum+sumOfLeftLeaves(root.right);
        return sum;
    }
  }

4.5二叉樹中和爲某一值的路徑(劍指Offer)

import java.util.ArrayList;  
/** 
public class TreeNode { 
    int val = 0; 
    TreeNode left = null; 
    TreeNode right = null; 
 
    public TreeNode(int val) { 
        this.val = val; 
        } 
*/  
public class Solution {  
    private ArrayList<Integer> child=new ArrayList<Integer>();  
    private ArrayList<ArrayList<Integer>> father=new ArrayList<ArrayList<Integer>>();  
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {  
        if(root==null)  
            return father;  
        child.add(root.val);  
        target-=root.val;                                  //通過一個節點就減去這個節點的值  
        if(target==0&&root.left==null&&root.right==null)   //關鍵1  如果是葉子結點且target已經減到0了  
            father.add(new ArrayList<Integer>(child));     //關鍵2  注意的是這種寫法  
        FindPath(root.left,target);                          
        FindPath(root.right,target);                         
        child.remove(child.size()-1);   //關鍵3  
        return father;  
    }  
}  

4.6樹的子結構—判斷B是不是A的子結構(劍指Offer)

輸入兩棵二叉樹A,B,判斷B是不是A的子結構。(ps:我們約定空樹不是任意一個樹的子結構)

/** 
public class TreeNode { 
    int val = 0; 
    TreeNode left = null; 
    TreeNode right = null; 
 
    public TreeNode(int val) { 
        this.val = val; 
 
    } 
 
} 
*/  
public class Solution {  
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {  
       boolean temp=false;     
       if(root1!=null && root2!=null){  
           if(root1.val==root2.val)                         //當遇到結點相等時,開始判斷  
              temp=doS(root1,root2);  
           if(!temp){                                      
              temp=HasSubtree(root1.left,root2);            //結點不相等,再判斷A樹左節點  
           }  
           if(!temp){  
              temp=HasSubtree(root1.right,root2);           //判斷A樹右節點  
           }  
       }  
      return temp;  
    }  
      
    public boolean doS(TreeNode root1,TreeNode root2)  
    {  
        if(root2==null)                                     //如果B樹走完了,說明A樹完全包含了B樹  
            return true;    
        if(root1==null)                                     //如果A樹走完了,B樹未走完,說明A樹不完全包含B樹,記住和上面不能顛倒  
            return false;            
        if(root1.val!=root2.val)                            //判斷結點是否相等,不相等返回false  
            return false;  
        return doS(root1.left,root2.left)&&doS(root1.right,root2.right);  //繼續判斷A樹B樹左節點,A樹B樹右節點  
    }  
 }  

4.7LeetCode110 Balanced Binary Tree(判斷是不是平衡二叉樹)

Given a binary tree, determine if it is height-balanced.

For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

/** 
 * Definition for a binary tree node. 
 * public class TreeNode { 
 *     int val; 
 *     TreeNode left; 
 *     TreeNode right; 
 *     TreeNode(int x) { val = x; } 
 * } 
 */  
class Solution {  
    boolean result=true;  
    public boolean isBalanced(TreeNode root) {  
        TestIsBalanced(root);  
        return result;  
    }  
    public int TestIsBalanced(TreeNode root){  
        if(root==null)  
            return 0;  
        int l=TestIsBalanced(root.left);  
        int r=TestIsBalanced(root.right);  
        if(Math.abs(l-r)>1)              //注意絕對值用法  
             result=false;               //注意這裏沒有return  
        return 1+Math.max(l,r);  
        }  
}  

4.8求二叉樹的最大寬度

public static int getMaxWidth(TreeNode root) {  
        if (root == null)  
            return 0;  
  
        Queue<TreeNode> queue = new ArrayDeque<TreeNode>();  
        int maxWitdth = 1; // 最大寬度  
        queue.add(root); // 入隊  
  
        while (true) {  
            int len = queue.size(); // 當前層的節點個數  
            if (len == 0)  
                break;  
            while (len > 0) {// 如果當前層,還有節點  
                TreeNode t = queue.poll();  
                len--;  
                if (t.left != null)  
                    queue.add(t.left); // 下一層節點入隊  
                if (t.right != null)  
                    queue.add(t.right);// 下一層節點入隊  
            }  
            maxWitdth = Math.max(maxWitdth, queue.size());  
        }  
        return maxWitdth;  
}  

4.9二叉樹的所有路徑

Given a binary tree, return all root-to-leaf paths.For example, given the following binary tree:

   1
 /   \
2     3
 \
  5

["1->2->5", "1->3"]
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<String> binaryTreePaths(TreeNode root) {
       List<String> test=new ArrayList<String>();   //數組是對象,引用傳遞
       if(root!=null) searchBT(root,"",test);
       return test;
    }
    public void searchBT(TreeNode root,String path,List<String> test)
    {
        if((root.left==null)&&(root.right==null)) test.add(path+root.val);//注意r:string+int就是string了 
        if(root.left!=null)  searchBT(root.left,path+root.val+"->",test);
        if(root.right!=null) searchBT(root.right,path+root.val+"->",test);    
    }
}

5.綜合算法

5.1矩形覆蓋(劍指Offer)

我們可以用21的小矩形橫着或者豎着去覆蓋更大的矩形。請問用n個21的小矩形無重疊地覆蓋一個2*n的大矩形,總共有多少種方法?

public class Solution {
    public int RectCover(int target) {
       if(target==1||target==0)
           return target;
       else if(target==2)
            return 2;
       else 
       return RectCover(target-1)+RectCover(target-2);
    }
}

5.2Leetcode121 Best Time to Buy and Sell Stock(買賣股票的最佳時機1)

Say you have an array for which the ith element is the price of a given stock on day i.

If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.
例子:

Input: [7, 1, 5, 3, 6, 4]
Output: 5
max. difference = 6-1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price)
Input: [7, 6, 4, 3, 1]
Output: 0
In this case, no transaction is done, i.e. max profit = 0.

解答:

class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length==0)
            return 0;
        int min=prices[0];              //先把第一個值設爲最小值
        int profit=0;                     
        for(int i=0;i<prices.length;i++)
        {
            if(prices[i]<min)          //如果當前值小於最小值(買入點),把最小值改爲當前值
                min=prices[i];
            if(prices[i]-min>profit)   //如果利潤大於以前的利潤,則把最大利潤換成當前情況的
                profit=prices[i]-min;
        }
        return profit;
      }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章