字节跳动面试高频题

🏡数组与排序
三数之和
给定一个包含 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;
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章