地上有一個m行和n列的方格。一個機器人從座標0,0的格子開始移動,每一次只能向左,右,上,下四個方向移動一格,可是不能進入行座標和列座標的數位之和大於k的格子。 例如,當k爲18時,機器人可以進入方格(35,37),由於3+5+3+7 = 18。可是,它不能進入方格(35,38),由於3+5+3+8 = 19。請問該機器人可以達到多少個格子?java
探索時判斷當前節點是否可達時的標準被:node
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佔據了矩陣中的第一行第二個格子以後,路徑不能再次進入該格子。數組
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
代碼: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小的結點。例如, (5,3,7,2,4,6,8) 中,按結點數值大小順序第三小結點的值爲4。spa
連接:牛客網
思路:
代碼:
/* 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; } }
請實現兩個函數,分別用來序列化和反序列化二叉樹
連接:牛客網
思路:
代碼:
/* 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
連接:牛客網
思路:
代碼:
/* 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"。
連接:牛客網
思路:
改進:
代碼:
/* 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"。
連接:牛客網
思路:
代碼:
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]。不能使用除法。
連接:牛客網
思路:
代碼:
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。
連接:牛客網
思路:
代碼:
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,三步走
一樣咱們能夠用三步走的方式計算二進制值相加: 5-101,7-111 第一步:相加各位的值,不算進位,獲得010,二進制每位相加就至關於各位作異或操做,101^111。
代碼:
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,要求不能使用乘除法、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。
連接:牛客網
思路:
代碼:
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對一一的翻轉這些單詞順序可不在行,你能幫助他麼?
連接:牛客網
思路:
代碼:
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,搞定它!
連接:牛客網
思路:
代碼:
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,輸出兩個數的乘積最小的。
連接:牛客網
思路:
設頭尾兩個指針,小於目標數則頭指針右移,大於則尾指針左移,相等則爲目標數,第一次遇到(間隔最遠)則爲乘積最小組合。
代碼:
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; } }