算法-劍指offer

機器人的運動範圍

地上有一個m行和n列的方格。一個機器人從座標0,0的格子開始移動,每一次只能向左,右,上,下四個方向移動一格,可是不能進入行座標和列座標的數位之和大於k的格子。 例如,當k爲18時,機器人可以進入方格(35,37),由於3+5+3+7 = 18。可是,它不能進入方格(35,38),由於3+5+3+8 = 19。請問該機器人可以達到多少個格子?java

連接:牛客網
思路:
  • 回溯法:
  • 從(0,0)開始,沒走成功一步標記當前位置爲true,而後向當前四個方向探索,返回1+4個方向的探索值。
  • 探索時判斷當前節點是否可達時的標準被:node

    • 當前節點在矩陣內
    • 當前節點未被訪問過
    • 當前節點知足limit限制
代碼:
public class Solution {
    public int movingCount(int threshold, int rows, int cols)
    {
        boolean[][] flag = new boolean[rows][cols];
        return move(threshold,rows,cols,0,0,flag);
    }
    
    public int move(int threshold,int rows,int cols,int r,int c,boolean[][] flag){
        
        if(r < 0 || r >= rows || c < 0 || c >= cols || flag[r][c] || numSum(r) + numSum(c) > threshold){
            return 0;
        }
        flag[r][c] = true;
        return move(threshold,rows,cols,r-1,c,flag) 
            + move(threshold,rows,cols,r+1,c,flag)
            + move(threshold,rows,cols,r,c-1,flag)
            + move(threshold,rows,cols,r,c+1,flag)
            + 1;
    }
    
    public int numSum(int x){
        int c = 0;
        while(x / 10 != 0){
            c += x % 10;
            x = x / 10;
        }
        return c + x;
    }
}

矩陣中的路徑

請設計一個函數,用來判斷在一個矩陣中是否存在一條包含某字符串全部字符的路徑。路徑能夠從矩陣中的任意一個格子開始,每一步能夠在矩陣中向左,向右,向上,向下移動一個格子。若是一條路徑通過了矩陣中的某一個格子,則以後不能再次進入這個格子。 例如 a b c e s f c s a d e e 這樣的3 X 4 矩陣中包含一條字符串"bcced"的路徑,可是矩陣中不包含"abcb"路徑,由於字符串的第一個字符b佔據了矩陣中的第一行第二個格子以後,路徑不能再次進入該格子。數組

連接:牛客網
思路:
  • 思路同上題差很少,修改一個條件:matrix[cur] != str[index]
代碼:
public class Solution {
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        for(int i = 0;i < rows;i++){
            for(int j = 0;j < cols;j++){
                boolean[] flag = new boolean[rows * cols];
                if(helper(matrix,rows,cols,i,j,str,0,flag))
                    return true;
            }
        }
        return false;
    }

    public boolean helper(char[] matrix,int rows,int cols,int r,int c,char[] str,int index,boolean[] flag){
        int cur = r * cols + c;
        if(r < 0 || r >= rows || c < 0 || c >= cols || flag[cur] || matrix[cur] != str[index]){
            return false;
        }
        flag[cur] = true;
        if(index == str.length - 1){
            return true;
        }
        index++;
        if(helper(matrix,rows,cols,r-1,c,str,index,flag)
            || helper(matrix,rows,cols,r+1,c,str,index,flag)
            || helper(matrix,rows,cols,r,c-1,str,index,flag)
            || helper(matrix,rows,cols,r,c+1,str,index,flag)){
            return true;
        }
        flag[cur] = false;
        return false;
        
    }

}

滑動窗口的最大值

給定一個數組和滑動窗口的大小,找出全部滑動窗口裏數值的最大值。例如,若是輸入數組{2,3,4,2,6,2,5,1}及滑動窗口的大小3,那麼一共存在6個滑動窗口,他們的最大值分別爲{4,4,6,6,6,5}; 針對數組{2,3,4,2,6,2,5,1}的滑動窗口有如下6個: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。app

連接:牛客網

思路:

  • 經過維護一個雙端隊列,隊列的第一個值保存最大值,當每次窗口滑動:函數

    • 一、判斷隊列第一個值是否失效。
    • 二、從隊尾開始比較,移出隊列全部比當前值小的值。

代碼:

import java.util.*;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size)
    {
        ArrayList<Integer> list = new ArrayList<>();
        if(size == 0){
            return list;
        }
        ArrayDeque<Integer> deque = new ArrayDeque<>();
        int begin = 0;
        for(int i = 0;i<num.length;i++){
            begin = i - size + 1;
            if(deque.isEmpty()){
                deque.add(i);
            }
            else if(begin > deque.peekFirst()){
                deque.pollFirst();
            }
            while((!deque.isEmpty()) && num[deque.peekLast()] <= num[i]){
                deque.pollLast();
            }
            deque.add(i);
            if(begin >= 0){
                list.add(num[deque.peekFirst()]);
            }
        }
        return list;
    }
}

數據流中的中位數

如何獲得一個數據流中的中位數?若是從數據流中讀出奇數個數值,那麼中位數就是全部數值排序以後位於中間的數值。若是從數據流中讀出偶數個數值,那麼中位數就是全部數值排序以後中間兩個數的平均值。咱們使用Insert()方法讀取數據流,使用GetMedian()方法獲取當前讀取數據的中位數。oop

連接:牛客網ui

思路:this

  • 方法一:經過二分查找,維護一個遞增集合List
  • 方法二:維護兩個堆,大根堆放大的那部分數,小根堆放小的那部分數據。

代碼:google

import java.util.ArrayList;
public class Solution {
 
    ArrayList<Integer> list = new ArrayList<Integer>();
    int size = 0;
    public void Insert(Integer num) {
        int lo = 0,ro = list.size()-1,mid = 0;
        while(lo <= ro){
            mid = (lo + ro) / 2;
            if(num < list.get(mid)){
                ro = mid - 1;
            }else if(num > list.get(mid)){
                lo = mid +1;
            }
        }
        list.add(mid,num);
        size++;
    }
 
    public Double GetMedian() {
        int cur = size / 2;
        if(size % 2 == 0){
            return (new Double(list.get(cur)) + new Double(list.get(cur-1))) / 2;
        }else{
            return new Double(list.get(cur));
        }
    }
}
import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {

    int count = 0;
    private PriorityQueue<Integer> minHeap = new PriorityQueue<>();
    private PriorityQueue<Integer> maxHeap = new PriorityQueue<>(15,new Comparator<Integer>(){
        public int compare(Integer o1,Integer o2){
            return o2 - o1;
        }
    });
    public void Insert(Integer num) {
        if(count % 2 == 0){
            maxHeap.offer(num);
            int cur = maxHeap.poll();
            minHeap.offer(cur);
        }else{
            minHeap.offer(num);
            int cur = minHeap.poll();
            maxHeap.offer(cur);
        }
        count++;
    }

    public Double GetMedian() {
        if(count % 2 == 0){
            return new Double(minHeap.peek() + maxHeap.peek()) /2 ;
        }else{
            return new Double(minHeap.peek());
        }
    }
}

二叉搜索樹的第k個節點

給定一棵二叉搜索樹,請找出其中的第k小的結點。例如, (5,3,7,2,4,6,8) 中,按結點數值大小順序第三小結點的值爲4。spa

連接:牛客網

思路:

  • 利用二叉搜索樹的中序遍歷獲得從小到大的順序,獲得第k個值。

代碼:

/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    int count = 0;
    TreeNode KthNode(TreeNode pRoot, int k)
    {
        if(pRoot != null){
            TreeNode node = KthNode(pRoot.left,k);
            if(node != null){
                return node;
            }
            if(++count == k){
                return pRoot;
            }
            node = KthNode(pRoot.right,k);
            if(node != null){
                return node;
            }
        }
        return null;
    }


}

序列化二叉樹

請實現兩個函數,分別用來序列化和反序列化二叉樹

連接:牛客網

思路:

  • 對於序列化:使用前序遍歷,遞歸的將二叉樹的值轉化爲字符,而且在每次二叉樹的結點不爲空時,在轉化val所得的字符以後添加一個' , '做爲分割。對於空節點則以 '#' 代替。
  • 對於反序列化:按照前序順序,遞歸的使用字符串中的字符建立一個二叉樹.

代碼:

/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    int index = -1;
    String Serialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        if(root == null){
            sb.append("#,");
            return sb.toString();
        }
        sb.append(root.val).append(",");
        sb.append(Serialize(root.left));
        sb.append(Serialize(root.right));
        return sb.toString();
  }
    TreeNode Deserialize(String str) {
       index++;
       if(index == str.length()){
           return null;
       }
       String[] strr = str.split(",");
        TreeNode node = null;
       if(!strr[index].equals("#")){
           node = new TreeNode(Integer.parseInt(strr[index]));
           node.left = Deserialize(str);
           node.right = Deserialize(str);
       }
       return node;
  }
}

把二叉樹打印成多行

從上到下按層打印二叉樹,同一層結點從左至右輸出。每一層輸出一行。

連接:牛客網

思路:

  • 按層次輸出二叉樹
  • 訪問根節點,並將根節點入隊。
  • 當隊列不空的時候,重複如下操做。

    • 一、彈出一個元素。做爲當前的根節點。
    • 二、若是根節點有左孩子,訪問左孩子,並將左孩子入隊。
    • 三、若是根節點有右孩子,訪問右孩子,並將右孩子入隊。

代碼:

import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;


/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<>();
        if(pRoot == null){
            return result;
        }
        ArrayList<Integer> list = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        int start = 0,end = 1;
        queue.add(pRoot);
        while(!queue.isEmpty()){
            start++;
            TreeNode node = queue.remove();
            list.add(node.val);
            if(node.left != null){
                queue.add(node.left);
            }
            if(node.right != null){
                queue.add(node.right);
            }
            if(start == end){
                start = 0;
                end = queue.size();
                result.add(list);
                list = new ArrayList<>();
            }
        }
        return result;
    }
    
}

按之字形順序打印二叉樹

請實現一個函數按照之字形打印二叉樹,即第一行按照從左到右的順序打印,第二層按照從右至左的順序打印,第三行按照從左到右的順序打印,其餘行以此類推。

連接:牛客網

思路:

  • 思路同上題差很少。

代碼:

import java.util.ArrayList;
import java.util.Stack;
/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        if(pRoot == null){
            return res;
        }
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<TreeNode> stack2 = new Stack<>();
        ArrayList<Integer> list = new ArrayList<>();
        stack1.add(pRoot);
        int start = 0,end = stack1.size(),size = 1;
        while(!stack1.isEmpty() || !stack2.isEmpty()){
            if(size % 2 == 1){
                TreeNode node = stack1.pop();
                list.add(node.val);
                if(node.left != null){
                    stack2.add(node.left);
                }
                if(node.right != null){
                    stack2.add(node.right);
                }
                start++;
                if(start == end){
                    start = 0;
                    end = stack2.size();
                    size++;
                    res.add(list);
                    list = new ArrayList<>();
                }
            }else{
                TreeNode node = stack2.pop();
                list.add(node.val);
                if(node.right != null){
                    stack1.add(node.right);
                }
                if(node.left != null){
                    stack1.add(node.left);
                }
                start++;
                if(start == end){
                    start = 0;
                    end = stack1.size();
                    size++;
                    res.add(list);
                    list = new ArrayList<>();
                }
            }
        }
        return res;
        
    }

}

對稱的二叉樹

請實現一個函數,用來判斷一顆二叉樹是否是對稱的。注意,若是一個二叉樹同此二叉樹的鏡像是一樣的,定義其爲對稱的。

連接:牛客網

思路:

  • 首先判斷左孩子是否等於右孩子
  • 接着遞歸判斷左孩子的左右孩子是否與右孩子的右左孩子對應相等。

代碼:

/*
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    boolean isSymmetrical(TreeNode pRoot)
    {
        if(pRoot == null){
            return true;
        }
        return helper(pRoot.left,pRoot.right);
    }
   
    boolean helper(TreeNode node1,TreeNode node2){
        if(node1 == null)
            return node2 == null;
        if(node2 == null || node1.val != node2.val)
            return false;
        return helper(node1.left,node2.right) && helper(node1.right,node2.left);
    }
}

二叉樹的下一個節點

給定一個二叉樹和其中的一個結點,請找出中序遍歷順序的下一個結點而且返回。注意,樹中的結點不只包含左右子結點,同時包含指向父結點的指針。

連接:牛客網

思路:

  • 節點爲空,則放回空。
  • 若是二叉樹的右孩子不爲空,則設置一指針從右孩子出發,一直沿着左孩子節點指針找到葉子節點,返回。
  • 節點不是根節點,若是節點是其父節點的左節點,則返回右節點;不然(節點是其父節點的右節點)則向上遍歷其父節點的父節點,重複以前的判斷。

代碼:

/*
public class TreeLinkNode {
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;

    TreeLinkNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public TreeLinkNode GetNext(TreeLinkNode pNode)
    {
        if(pNode == null){
            return null;
        }
        if(pNode.right != null){
            TreeLinkNode node = pNode.right;
            while(node.left != null){
                node = node.left;
            }
            return node;
        }
        TreeLinkNode nNode = pNode.next;
        while(nNode != null){
            if(nNode.left == pNode){
                return nNode;
            }
            pNode = nNode;
            nNode = nNode.next;
        }
        return null;
    }
}

刪除鏈表中重複的結點

在一個排序的鏈表中,存在重複的結點,請刪除該鏈表中重複的結點,重複的結點不保留,返回鏈表頭指針。 例如,鏈表1->2->3->3->4->4->5 處理後爲 1->2->5

連接:牛客網

思路:

  • 新建一個頭結點
  • 若是當前節點的下一節點nNode等於下下節點nNode2,nNode2指向其下一節點即nNode2 = nNode2.next,重複判斷直到nNode跟nNode2不相等,將當前節點下一節點指向nNode2,continue跳出當前循環。
  • 不然cur指向下一節點。

代碼:

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public ListNode deleteDuplication(ListNode pHead)
    {
        ListNode cur = new ListNode(-1);
        cur.next = pHead;
        ListNode res = cur;
        while(cur.next != null){
            ListNode nNode = cur.next;
            if(nNode.next != null){
                ListNode nNode2 = nNode.next;
                if(nNode2 != null && nNode.val == nNode2.val){
                    while(nNode2 != null && nNode.val == nNode2.val){
                        nNode2 = nNode2.next;
                    }
                    cur.next = nNode2;
                    continue;
                }
            }
            cur = nNode;
        }
        return res.next;
    }
}

字符流中第一個不重複的字符

請實現一個函數用來找出字符流中第一個只出現一次的字符。例如,當從字符流中只讀出前兩個字符"go"時,第一個只出現一次的字符是"g"。當從該字符流中讀出前六個字符「google"時,第一個只出現一次的字符是"l"。

連接:牛客網

思路:

  • 用一快一慢的指針開始行走,直到二者相遇,則相遇點在環內,計算出環的節點數n。
  • 讓指針p1從起點先走n步,p2纔開始從起點出發,兩個指針相遇的點即爲環的入口。

改進:

  • 第一步同上。
  • 讓指針p1從起點出發,指針p2從相遇點出發,二者相遇點即爲環的入口。證實以下圖:

clipboard.png

代碼:

/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        if(pHead == null || pHead.next == null){
            return null;
        }
        ListNode slow = pHead.next;
        ListNode fast = pHead.next.next;
        while(slow != fast){
            if(slow.next != null && fast.next != null && fast.next.next != null){
                slow = slow.next;
                fast = fast.next.next;
            }else{
                return null;
            }
        }
        slow = pHead;
        while(slow != fast){
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
    }
}

字符流中第一個不重複的字符

請實現一個函數用來找出字符流中第一個只出現一次的字符。例如,當從字符流中只讀出前兩個字符"go"時,第一個只出現一次的字符是"g"。當從該字符流中讀出前六個字符「google"時,第一個只出現一次的字符是"l"。

連接:牛客網

思路:

  • 用一個128的數組來統計每次字符出現的字數
  • 用一個隊列,若是第一次遇到ch字符,則插入隊列,其餘狀況不插入
  • 求解第一個出現的字符,判斷隊首元素是否只出現一次,若是是直接返回,不然彈出重複該步驟
  • 時間複雜度O(1),空間複雜度O(n)

代碼:

import java.util.Queue;
import java.util.LinkedList;
public class Solution {
    //Insert one char from stringstream
    int[] arr = new int[256];
    Queue<Character> queue = new LinkedList<>();
    public void Insert(char ch)
    {
        if(queue.contains(ch)){
            arr[ch]++;
        }else{
            queue.add(ch);
            arr[ch] = 1;
        }
    }
  //return the first appearence once char in current stringstream
    public char FirstAppearingOnce()
    {
        while(!queue.isEmpty() && arr[queue.peek()] > 1){
            queue.poll();
        }
        if(queue.isEmpty()){
            return '#';
        }
        return queue.peek();
    }
}

構建乘積數組

給定一個數組A[0,1,...,n-1],請構建一個數組B[0,1,...,n-1],其中B中的元素B[i]=A[0]A[1]...A[i-1]A[i+1]...A[n-1]。不能使用除法。

連接:牛客網

思路:

  • 先計算A[0]...A[i-1]這部分
  • 在計算A[i+1]...A[n]這部分

代碼:

import java.util.ArrayList;
public class Solution {
    public int[] multiply(int[] A) {
        int length = A.length;
        int[] B = new int[length];
        B[0] = 1;
        int tmp = 1;
        for(int i = 1;i<length;i++){
            B[i] = B[i-1]*A[i-1];
        }
        for(int i = length - 2;i>=0;i--){
            tmp = A[i+1] * tmp;
            B[i] = B[i] * tmp;
        }
        return B;
    }
}

數組中重複的數字

在一個長度爲n的數組裏的全部數字都在0到n-1的範圍內。 數組中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每一個數字重複幾回。請找出數組中任意一個重複的數字。 例如,若是輸入長度爲7的數組{2,3,1,0,2,5,3},那麼對應的輸出是第一個重複的數字2。

連接:牛客網

思路:

  • 由於全部數字都小於n,因此能夠利用現有數組設置標記,當一個數字被訪問事後,能夠設置對應位上的數+n,以後遇到相同的數時,會發現對應做爲上的數已經大於等於n了,那麼直接返回這個數便可。

代碼:

public class Solution {
    // Parameters:
    //    numbers:     an array of integers
    //    length:      the length of array numbers
    //    duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation;
    //                  Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++
    //    這裏要特別注意~返回任意重複的一個,賦值duplication[0]
    // Return value:       true if the input is valid, and there are some duplications in the array number
    //                     otherwise false
    public boolean duplicate(int numbers[],int length,int [] duplication) {
         
        for(int i = 0;i<length;i++){
            int tmp = numbers[i];
            tmp = tmp < length ? tmp : tmp - length;
            if(numbers[tmp] >= length){
                duplication[0] = tmp;
                return true;
            }else{
                numbers[tmp] += length;
            }
        }
        return false;
    }
}

把字符串轉化爲整數

將一個字符串轉換成一個整數(實現Integer.valueOf(string)的功能,可是string不符合數字要求時返回0),要求不能使用字符串轉換整數的庫函數。 數值爲0或者字符串不是一個合法的數值則返回0。

連接:牛客網

思路:

代碼:

public class Solution {
    public int StrToInt(String str) {
        int length = str.length();
        if(length == 0){
            return 0;
        }
        int flag = 0,res = 0;
        if(str.charAt(0) == '-'){
            flag = 1;
        }
        
        for(int i = flag;i<length;i++){
            if(str.charAt(i) == '+'){
                continue;
            }
            if(str.charAt(i) < '0' || str.charAt(i) > '9'){
                return 0;
            }
            res = res * 10 + str.charAt(i) - '0';
        }
        return flag == 1 ? -1 * res : res;
    }
}

不用加減乘除作加法

寫一個函數,求兩個整數之和,要求在函數體內不得使用+、-、*、/四則運算符號。

連接:牛客網

思路:

  • 首先看十進制是如何作的: 5+7=12,三步走

    • 第一步:相加各位的值,不算進位,獲得2。
    • 第二步:計算進位值,獲得10. 若是這一步的進位值爲0,那麼第一步獲得的值就是最終結果。
    • 第三步:重複上述兩步,只是相加的值變成上述兩步的獲得的結果2和10,獲得12。
  • 一樣咱們能夠用三步走的方式計算二進制值相加: 5-101,7-111 第一步:相加各位的值,不算進位,獲得010,二進制每位相加就至關於各位作異或操做,101^111。

    • 第二步:計算進位值,獲得1010,至關於各位作與操做獲得101,再向左移一位獲得1010,(101&111)<<1。
    • 第三步重複上述兩步, 各位相加 010^1010=1000,進位值爲100=(010&1010)<<1。
      繼續重複上述兩步:1000^100 = 1100,進位值爲0,跳出循環,1100爲最終結果

代碼:

public class Solution {
    public int Add(int num1,int num2) {
        while(num2 != 0){
            int tmp = num1 ^ num2;
            num2 = (num1 & num2) << 1;
            num1 = tmp;
        }
        return num1;
    }
}

求1+2+3+...+n

求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等關鍵字及條件判斷語句(A?B:C)。

連接:牛客網

思路:

  • 遞歸加&&運算短路機制

代碼:

public class Solution {
    public int Sum_Solution(int n) {
        int res = n;
        boolean flag = (res > 0) && (res += Sum_Solution(n-1)) > 0;
        return res;
    }
}

撲克牌順序

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。

連接:牛客網

思路:

  • 先統計出大小王(0)的數量,而後將數組排序,比較相鄰兩個數之間的差值總和與大小王數量的高低。

代碼:

import java.util.Arrays;
public class Solution {
    public boolean isContinuous(int [] numbers) {
        int length = numbers.length;
        if(length == 0){
            return false;
        }
        int count = 0;
        for(int i = 0;i<length;i++){
            if(numbers[i] == 0){
                count++;
            }
        }
        Arrays.sort(numbers);
        for(int i = count;i<length-1;i++){
            if(numbers[i+1] == numbers[i]){
                return false;
            }
            if(numbers[i+1] - numbers[i] > 1){
                count -= numbers[i+1] - numbers[i] - 1;
            }
            if(count < 0){
                return false;
            }
        }
        return true;
    }
}

反轉單詞順序列

牛客最近來了一個新員工Fish,天天早晨老是會拿着一本英文雜誌,寫些句子在本子上。同事Cat對Fish寫的內容頗感興趣,有一天他向Fish借來翻看,但卻讀不懂它的意思。例如,「student. a am I」。後來才意識到,這傢伙原來把句子單詞的順序翻轉了,正確的句子應該是「I am a student.」。Cat對一一的翻轉這些單詞順序可不在行,你能幫助他麼?

連接:牛客網

思路:

  • 以" " 空格分割
  • 經過進行StringBuilder進行拼接
  • 擴展,當全部的字符都翻轉時,可先經過翻轉所有字符,再翻轉單詞

代碼:

public class Solution {
    public String ReverseSentence(String str) {
        if(str.trim().equals("")){
            return str;
        }
        String[] strr = str.split(" ");
        StringBuilder sb = new StringBuilder();
        for(int i = 0;i<strr.length;i++){
            sb.append(strr[strr.length - 1 - i]).append(" ");
        }
        return sb.substring(0,sb.length()-1).toString();
    }
}

左旋裝字符串

彙編語言中有一種移位指令叫作循環左移(ROL),如今有個簡單的任務,就是用字符串模擬這個指令的運算結果。對於一個給定的字符序列S,請你把其循環左移K位後的序列輸出。例如,字符序列S=」abcXYZdef」,要求輸出循環左移3位後的結果,即「XYZdefabc」。是否是很簡單?OK,搞定它!

連接:牛客網

思路:

  • 見代碼
  • 另外一種思路:將數組分爲A、B兩部分,先各翻轉A、B,最後翻轉數組便可。

代碼:

public class Solution {
    public String LeftRotateString(String str,int n) {
        if(str.trim().equals("")){
            return str;
        }
        String cur = str + str;
        return cur.substring(n,str.length() + n);
    }
}

和爲S的兩個數字

輸入一個遞增排序的數組和一個數字S,在數組中查找兩個數,使得他們的和正好是S,若是有多對數字的和等於S,輸出兩個數的乘積最小的。

連接:牛客網

思路:
設頭尾兩個指針,小於目標數則頭指針右移,大於則尾指針左移,相等則爲目標數,第一次遇到(間隔最遠)則爲乘積最小組合。
代碼:

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        if(array == null || array.length == 0 || sum == 0){
            return result;
        }
        int start = 0,end = array.length-1;
        while(start <= end){
            int curSum = array[start] + array[end];
            if(curSum == sum){
                result.add(array[start]);
                result.add(array[end]);
                break;
            }
            else if(curSum < sum){
                start++;
            }
            else{
                end--;
            }
            
        }
        return result;
    }
}
相關文章
相關標籤/搜索