字節跳動面試高頻題

🏡數組與排序
三數之和
給定一個包含 n 個整數的數組 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重複的三元組。 注意:答案中不可以包含重複的三元組。
在這裏插入圖片描述

class Solution {
    public static List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ans = new ArrayList();
        int len = nums.length;
        if(nums == null || len < 3) return ans;
        Arrays.sort(nums); // 排序
        for (int i = 0; i < len ; i++) {
            if(nums[i] > 0) break; // 如果當前數字大於0,則三數之和一定大於0,所以結束循環
            if(i > 0 && nums[i] == nums[i-1]) continue; // 去重
            int L = i+1;
            int R = len-1;
            while(L < R){
                int sum = nums[i] + nums[L] + nums[R];
                if(sum == 0){
                    ans.add(Arrays.asList(nums[i],nums[L],nums[R]));
                    while (L<R && nums[L] == nums[L+1]) L++; // 去重
                    while (L<R && nums[R] == nums[R-1]) R--; // 去重
                    L++;
                    R--;
                }
                else if (sum < 0) L++;
                else if (sum > 0) R--;
            }
        }        
        return ans;
    }
}

島嶼的最大面積
給定一個包含了一些 0 和 1的非空二維數組 grid , 一個 島嶼 是由四個方向 (水平或垂直) 的 1 (代表土地) 構成的組合。你可以假設二維矩陣的四個邊緣都被水包圍着。
找到給定的二維數組中最大的島嶼面積。(如果沒有島嶼,則返回面積爲0。)

在這裏插入圖片描述

class Solution {
    public int maxAreaOfIsland(int[][] grid) {
        // 記錄最大值
        int max = 0;

        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[i].length; j++) {
                int temp = DFS(i, j, grid);
                max = temp > max ? temp : max;
            }
        }
        return max;
    }

    public int DFS(int i, int j, int[][] grid) {
        // 邊界判斷
        if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length) {
            return 0;
        }

        // 島嶼爲0、1判斷
        if (grid[i][j] == 0) {
            return 0;
        }

        // 標記grid[i][j] = 0
        grid[i][j] = 0;
        // 四個方向遞歸
        return 1 + DFS(i-1, j, grid)
                + DFS(i+1, j, grid)
                + DFS(i, j-1, grid)
                + DFS(i, j+1, grid);
    }
}

搜索旋轉排序數組
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。
( 例如,數組 [0,1,2,4,5,6,7] 可能變爲 [4,5,6,7,0,1,2] )。
搜索一個給定的目標值,如果數組中存在這個目標值,則返回它的索引,否則返回 -1 。
你可以假設數組中不存在重複的元素。
你的算法時間複雜度必須是 O(log n) 級別。

在這裏插入圖片描述
代碼:

class Solution {
    public int search(int[] nums, int target) {
    	return search(nums, 0, nums.length-1, target);
    }
    private int search(int[] nums, int l, int r,int target){
    	if(l > r){
    		return -1;
    	}
    	int mid = (l+r)/2;
    	if(nums[mid] == target){
    		return mid;
    	}
    	if(nums[mid] < nums[r]){//右側有序
    		if(target > nums[mid] && target <= nums[r]){//目標值在右側
    			return search(nums, mid+1, r, target);
    		}else{
    			return search(nums, l, mid-1, target);
    		}
    	}else{
    		if(target < nums[mid] && target >= nums[l]){
    			return search(nums, l, mid-1, target);
    		}else{
    			return search(nums, mid+1, r, target);
    		}
    	}
    }
}

朋友圈
班上有 N 名學生。其中有些人是朋友,有些則不是。他們的友誼具有是傳遞性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那麼我們可以認爲 A 也是 C 的朋友。所謂的朋友圈,是指所有朋友的集合。
給定一個 N * N 的矩陣 M,表示班級中學生之間的朋友關係。如果M[i][j] = 1,表示已知第 i 個和 j 個學生互爲朋友關係,否則爲不知道。你必須輸出所有學生中的已知的朋友圈總數。

在這裏插入圖片描述
代碼:

class Solution {
    public int findCircleNum(int[][] M) {
        int len=M.length;
        if(len<2){
            return len;
        }
        int []help=new int[len];
        int cnt=0;
        for(int i=0;i<len;++i){
            if(help[i]==0){
                bfs(M,i,help);
                cnt++;
            }
        }
        return cnt;
    }
    private void bfs(int[][] graph,int node,int[] help){
        int[] queue=new int[graph.length];
        int cnt=1;
        queue[0]=node;
        help[node]=1;
        for (int i=0;i<cnt;++i){
            for (int j=0;j<graph[queue[i]].length;++j){
                if (queue[i]!=j&&graph[queue[i]][j]==1&&help[j]==0){
                        help[j]=1;
                        queue[cnt++]=j;
                }
            }
        }
    }
}

接雨水
給定 n 個非負整數表示每個寬度爲 1 的柱子的高度圖,計算按此排列的柱子,下雨之後能接多少雨水。
在這裏插入圖片描述

class Solution {
    public int trap(int[] height) {
        if(height == null || height.length <= 2)
            return 0;
        int maxL = height[0];
        int[] maxRs = new int[height.length];
        int waterSum = 0;//計算總的水量
        int maxR = 0;
        for(int i = height.length - 1; i >= 0; i--){
            if(height[i] > maxR) {
                maxRs[i] = maxR = height[i];
            }
            else {
                maxRs[i] = maxR;
            }
        }
        for(int i = 1; i < height.length - 1; i++){
            if(height[i] > maxL) {
                maxL = height[i];//更新左邊最大值
            }
                waterSum += Math.max(Math.min(maxL, maxRs[i]) - height[i], 0);
        }
        return waterSum;
        
      }
}

反轉鏈表
反轉一個單鏈表。
在這裏插入圖片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) return head;
        ListNode p = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return p;
    }
}

兩數相加
給出兩個 非空 的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照 逆序 的方式存儲的,並且它們的每個節點只能存儲 一位 數字。
如果,我們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。
您可以假設除了數字 0 之外,這兩個數都不會以 0 開頭。

在這裏插入圖片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
         if(l1==null){//因爲l1是基準鏈表,要是l1到尾部了,l2就算還有,直接返回l2的剩餘部分
            return l2;
        }
        if(l2==null){//這裏l2到尾部了,l1需要進行判斷,尾部是否大於10,要去進位。
        //比如l1:9,9 .l2:9 一次運算過後l2到尾部,l1變爲8,10,這時候依然當做l2有個0去進位
            if(l1.val>=10){
                l2 = new ListNode(0);
                l2.next = null;
            }else{
                 return l1;
            }
           
        }
        
        int temp = l1.val+l2.val;
        l1.val = temp%10;
        if(temp>=10){  //說明l1應該進位
            if(l1.next==null){//要是l1沒有下一位,則new一個節點進行連接
                l1.next = new ListNode(1); 
            }else{
                l1.next.val++; //l1有下一個節點,直接下一個節點的值加一
            }
        }       
        
        l1.next = addTwoNumbers(l1.next,l2.next);//用於重新連接攜帶新的值的每個l1節點
        
        return l1;
    }
}


買賣股票的最佳時機
給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。
如果你最多隻允許完成一筆交易(即買入和賣出一支股票),設計一個算法來計算你所能獲取的最大利潤。
注意你不能在買入股票前賣出股票。

在這裏插入圖片描述

class Solution {
    public static void main(String args[]) {
        int[] prices = new int[] {7,1,5,3,6,4};
        int max = maxProfit(prices);
        System.out.println(max);
    }
 
    public static int maxProfit(int[] prices) {
        if(prices.length <= 1) {
            return 0;
        }
        int min = prices[0];
        int max = 0;
        for(int i = 1; i < prices.length; i++) {
            max = Math.max(max, prices[i] - min);
            min = Math.min(min, prices[i]);
        }
        return max;
    }
}

最大子序和
給定一個整數數組 nums ,找到一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和。
在這裏插入圖片描述

public class Solution { 
    
     public int maxSubArray(int[] nums) { 
 
          int len = nums.length; 
 
          if (len == 0) {
 
                return 0; 
          } 
 
 
          int[] dp = new int[len]; 
 
          dp[0] = nums[0]; 
 
          for (int i = 1; i < len; i++) { 
 
              dp[i] = Math.max(nums[i], dp[i - 1] + nums[i]);
 
          }
 
 
          // 最後這一步,是求一個全局的最優值 
          int res = dp[0]; 
 
          for (int i = 1; i < len; i++) { 
 
               res = Math.max(res,dp[i]); } return res; 
 
           }
 }

最小棧
設計一個支持 push,pop,top 操作,並能在常數時間內檢索到最小元素的棧。
push(x) – 將元素 x 推入棧中。
pop() – 刪除棧頂的元素。
top() – 獲取棧頂元素。
getMin() – 檢索棧中的最小元素。

在這裏插入圖片描述

class MinStack {
    private Node head;

    public void push(int x) {
        if (head == null)
            head = new Node(x, x);
        else
            head = new Node(x, Math.min(x, head.min), head);
    }

    public void pop() {
        head = head.next;
    }

    public int top() {
        return head.val;
    }

    public int getMin() {
        return head.min;
    }

    private class Node {
        int val;
        int min;
        Node next;

        private Node(int val, int min) {
            this(val, min, null);
        }

        private Node(int val, int min, Node next) {
            this.val = val;
            this.min = min;
            this.next = next;
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章