byte dance

  1. K 个一组翻转链表
    给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例:

给你这个链表:1->2->3->4->5

当 k = 2 时,应当返回: 2->1->4->3->5

当 k = 3 时,应当返回: 3->2->1->4->5

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
        public ListNode reverseKGroup(ListNode head, int k) {
            ListNode dummy = new ListNode(-1);
            dummy.next = head;
            //前驱节点
            ListNode pre = dummy;
            //后驱节点
            ListNode end = dummy;
            while(end!=null){
                //后移k个节点,到达翻转链表的末尾节点
                for(int i=0;i<k&&end!=null;i++) end = end.next;
                //如果此时末尾节点为null,则说明长度不够,直接结束
                if(end==null) break;
                //next节点保存后驱节点
                ListNode next = end.next;
                //start指向翻转链表的开始
                ListNode start = pre.next;
                //end指向翻转链表的结束,这里将end与之后的链表切断
                end.next = null;
                //翻转之后的头节点由前驱节点的next指向,与前驱连上
                pre.next = reverse(start);
                //翻转以后start节点为该翻转链表的末尾,指向后驱
                start.next = next;
                //前驱节点后后驱节点都指向start
                pre = start;
                end = start;
            }
            return dummy.next;
        }

        private ListNode reverse(ListNode node){
            ListNode pre = null;
            ListNode cur = node;
            while(cur!=null){
                ListNode next = cur.next;
                cur.next = pre;
                pre = cur;
                cur=next;
            }
            return pre;
        }



}
  1. 买卖股票的最佳时机
    给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。

注意:你不能在买入股票前卖出股票。

示例 1:

输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例 2:

输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

class Solution {
    public int maxProfit(int[] prices) {
        //dp[i][k][0] = max(dp[i-1][k][0],dp[i-1][k][1]+prices[i])
        //dp[i][k][1] = max(dp[i-1][k][1],dp[i-1][k-1][0]-prices[i])
        //dp[i][0][0] = 0;不允许交易利润为0
        //dp[i][0][1] = -infinity;不允许交易持有不可能发生
        //dp[-1][k][0] = -infinity;时间从第0天开始,不可能为-1
        //dp[-1][k][1] = -infinity;时间从第0天开始,不可能为-1
        //带入k=1; dp[i][1][0] = max(dp[i-1][1][0],dp[i-1][1][1]+prices[i]);
        //        dp[i]][1][1] = max(dp[i-1][1][1],dp[i-1][0][0]-prices[i]);
        //因为dp[i-1][0][0] = 0; 所以dp[i][1][1] = max(dp[i-1][1][1],-prices[i]);
        //与k无关
        //最终的状态方程为 dp[i][0] = max(dp[i-1][0],dp[i-1][1]+prices[i]);
        //                dp[i][1] = max(dp[i-1][1],-prices[i]);
        int n = prices.length;
        if(n==0)
        return 0;
        int dp_sum0 = 0;
        int dp_sum1 = Integer.MIN_VALUE;
        for(int i=0;i<n;i++){

          //  dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]+prices[i]);
            dp_sum0 = Math.max(dp_sum0,dp_sum1+prices[i]);
          //  dp[i][1] = Math.max(dp[i-1][1],-prices[i]);
          dp_sum1 = Math.max(dp_sum1,-prices[i]);
        }
        return dp_sum0;
    }
}
  1. 三数之和
    给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ans = new ArrayList<>();
        Arrays.sort(nums);
        for(int k=0;k<nums.length-2;k++){
            if(nums[k]>0)
            break;
            if(k>0&&nums[k]==nums[k-1])
            continue;
            int i = k+1;
            int j = nums.length-1;
            while(i<j){
                int sum = nums[k]+nums[i]+nums[j];
                if(sum>0){
                    while(i<j&&nums[j]==nums[--j]);
                }else if(sum<0){
                    while(i<j&&nums[i]==nums[++i]);
                }else if(sum==0){
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[k]);
                    list.add(nums[i]);
                    list.add(nums[j]);
                    ans.add(list);
                    while(i<j&&nums[i]==nums[++i]);
                    while(i<j&&nums[j]==nums[--j]);
                }
            }
        }
        return ans;
    }
}
  1. 最小栈
    设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。

示例:

输入:
[“MinStack”,“push”,“push”,“push”,“getMin”,“pop”,“top”,“getMin”]
[[],[-2],[0],[-3],[],[],[],[]]

输出:
[null,null,null,null,-3,null,0,-2]

解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.

class MinStack {
    Stack<Integer> st1 ;
    Stack<Integer> st2 ;
    /** initialize your data structure here. */
    public MinStack() {
        st1 = new Stack<>();
        st2 = new Stack<>();
    }
    
    public void push(int x) {
        st1.push(x);
        if(st2.isEmpty()||st2.peek()>=x)
        st2.push(x);
    }
    
    public void pop() {
        if(st1.pop().equals(st2.peek()))
            st2.pop();
    }
    
    public int top() {
       return st1.peek();
    }
    
    public int getMin() {
       return st2.peek();
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(x);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */
  1. 二叉树中的最大路径和
    给定一个非空二叉树,返回其最大路径和。

本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。

示例 1:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int max = Integer.MIN_VALUE;
    public int maxPathSum(TreeNode root) {
        heper(root);
        return max;
    }

    private int heper(TreeNode root){
        if(root==null)
        return 0;
        int left = Math.max(heper(root.left),0) ;
        int right = Math.max(heper(root.right),0);
        max = Math.max(max,root.val+left+right);
        return root.val+Math.max(left,right);
    }
}
  1. 无重复字符的最长子串
    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:

输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:

输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int max = 0;
        Map<Character,Integer> map = new HashMap<>();
        int left = 0;
        for(int i=0;i<s.length();i++){
            char c = s.charAt(i);
            if(map.containsKey(c)){
                left = Math.max(left,map.get(c)+1);
            }
            map.put(c,i);
            max = Math.max(max,i-left+1);
        }
        return max;
    }
}
  1. 合并两个有序数组
    给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。

说明:

初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。

示例:

输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3

输出: [1,2,2,3,5,6]

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int index =m+n-1;
        m--;
        n--;
        while(m>=0&&n>=0){
            if(nums1[m]>nums2[n]){
                nums1[index--]=nums1[m--];
            }else {
                nums1[index--] = nums2[n--];
            }
        }
        while(n>=0){
            nums1[index--] = nums2[n--];
        }
        
    }
}
  1. 将有序数组转换为二叉搜索树
    将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。

本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

示例:

给定有序数组: [-10,-3,0,5,9],

一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:

  0
 / \

-3 9
/ /
-10 5

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int[] nums;
    public TreeNode sortedArrayToBST(int[] nums) {
        this.nums = nums;
        return heper(0,nums.length-1);
    }

    private TreeNode heper(int left,int right){
        if(left>right)
        return null;
        int mid = left+(right-left)/2;
        TreeNode root = new TreeNode(nums[mid]);
        root.left = heper(left,mid-1);
        root.right = heper(mid+1,right);
        return root;
    }
}
  1. 二叉树的最近公共祖先
    给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]

在这里插入图片描述
示例 1:

输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 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 TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root==null||root==p||root==q)
        return root;
        TreeNode left = lowestCommonAncestor(root.left,p,q);
        TreeNode right = lowestCommonAncestor(root.right,p,q);
        if(left==null)
        return right;
        if(right==null)
        return left;
        return root;
    }
}
  1. 搜索旋转排序数组
    假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

你可以假设数组中不存在重复的元素。

你的算法时间复杂度必须是 O(log n) 级别。

示例 1:

输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4
示例 2:

输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1

class Solution {
    public int search(int[] nums, int target) {
        if(nums.length==0)
        return -1;
        int left = 0;
        int right = nums.length-1;
        while(left<=right){
            int mid = left+(right-left)/2;
            if(nums[mid]>nums[right]){
                left=mid+1;
            }else if(nums[mid]<nums[right]){
                right=mid;
            }else break;
        }
        int index = left;
            left = 0;
            right = index-1;
            while(left<=right){
                int mid = left+(right-left)/2;
                if(nums[mid]==target)
                return mid;
                else if(nums[mid]<target){
                    left=mid+1;
                }else if(nums[mid]>target){
                    right=mid-1;
                }
            }
            left = index;
            right = nums.length-1;
            while(left<=right){
                int mid = left+(right-left)/2;
                if(nums[mid]==target)
                return mid;
                else if(nums[mid]<target){
                    left=mid+1;
                }else if(nums[mid]>target){
                    right=mid-1;
                }
            }            
            return -1;
    }
}
  1. 零钱兑换
    给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

示例 1:

输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:

输入: coins = [2], amount = 3
输出: -1

class Solution {
    public int coinChange(int[] coins, int amount) {
        int[] dp = new int[amount+1];
        for(int i=0;i<=amount;i++){
            dp[i] = Integer.MAX_VALUE/2;
        }
        dp[0] = 0;
        for(int coin:coins){
            for(int i=coin;i<=amount;i++){
                dp[i] = Math.min(dp[i],dp[i-coin]+1);
            }
        }
        return dp[amount]==Integer.MAX_VALUE/2?-1:dp[amount];
    }
}
  1. 删除排序链表中的重复元素
    给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。

示例 1:

输入: 1->1->2
输出: 1->2
示例 2:

输入: 1->1->2->3->3
输出: 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;
        ListNode ans = new ListNode(-1);
        ans.next = head;
        ListNode slow = ans.next;
        ListNode fast = slow.next;
        while(fast!=null){
            while(fast!=null&&fast.val==slow.val){
                fast = fast.next;
            }
            slow.next = fast;
            slow = fast;
            if(fast!=null)
            fast=fast.next;
        }
        return ans.next;
    }
}
  1. 反转链表
    反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

/**
 * 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 pre = null;
        ListNode cur = head;
        while(cur!=null){
            ListNode next = cur.next;
            cur.next = pre;
            pre=cur;
            cur = next;
        }
        return pre;
    }
}
  1. 数组中的第K个最大元素
    在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:

输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例 2:

输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4

class Solution {

    public int findKthLargest(int[] nums, int k) {
        int len = nums.length;
        int left = 0;
        int right = nums.length-1;
        int target = len-k;
        while(true){
            int index = quick(nums,left,right);
            if(index==target){
                return nums[index];
            }else if(index>target){
                right = index-1;
            }else if(index<target){
                left = index+1;
            }
        }
      //  return -1;
    }

    private int quick(int[] nums,int left ,int right){
        int privot = nums[left];
        int j = left;
        for(int i=left+1;i<=right;i++){
            if(nums[i]<privot){
                j++;
                swap(nums,i,j);
            }
        }
        swap(nums,left,j);
        return j;
    }

    private void swap(int[] nums,int index1,int index2){
        int tmp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = tmp;
    }

}
  1. 合并区间
    给出一个区间的集合,请合并所有重叠的区间。

示例 1:

输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:

输入: [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。

class Solution {
    public int[][] merge(int[][] intervals) {
        if(intervals==null||intervals.length==0||intervals[0].length==0)
        return intervals;
        Arrays.sort(intervals,(o1,o2)->{
            return o1[0]==o2[0]?o2[1]-o1[1]:o1[0]-o2[0];
        });
        int end = intervals[0][1];
        int start = intervals[0][0];
        List<int[]> list = new ArrayList<>();
        for(int i=1;i<intervals.length;i++){
            if(end>=intervals[i][0]){
                end = Math.max(end,intervals[i][1]);
            }else{
                int[] tmp = new int[]{start,end};
                list.add(tmp);
                start = intervals[i][0];
                end = intervals[i][1];
            }
        }
        if(list.size()==0){
            int[] tmp = new int[]{start,end};
            list.add(tmp);
        }

        if(list.get(list.size()-1)[1]!=end){
            int[] tmp = new int[]{start,end};
            list.add(tmp);
        }
        int[][] ans = new int[list.size()][2];
        for(int i=0;i<list.size();i++){
            ans[i][0]=list.get(i)[0];
            ans[i][1] =list.get(i)[1];
        }
        return ans;
    }
}
  1. 二叉树的层序遍历
    给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ans = new ArrayList<>();
        List<TreeNode> nodes = new ArrayList<>();
        List<Integer> list = new ArrayList<>();
        if(root==null)
        return ans;
        int count =0;
        nodes.add(root);
        while(nodes.size()!=0){
            if(count==0){
                ans.add(list);
                count = nodes.size();
                list = new ArrayList<>();
            }
            TreeNode tmp = nodes.remove(0);
            list.add(tmp.val);
            if(tmp.left!=null)
            nodes.add(tmp.left);
            if(tmp.right!=null)
            nodes.add(tmp.right);
            count--;
        }
        ans.add(list);
        ans.remove(0);
        return ans;
    }
}
  1. 零钱兑换 II
    给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。

示例 1:

输入: amount = 5, coins = [1, 2, 5]
输出: 4
解释: 有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1
示例 2:

输入: amount = 3, coins = [2]
输出: 0
解释: 只用面额2的硬币不能凑成总金额3。
示例 3:

输入: amount = 10, coins = [10]
输出: 1

class Solution {
    public int change(int amount, int[] coins) {
        int[] dp = new int[amount+1];
        dp[0]=1;
        for(int coin:coins){
            for(int i=1;i<=amount;i++){
                if(coin<=i){
                    dp[i]+=dp[i-coin];
                }
            }
        }
        return dp[amount];
    }

}

剑指 Offer 09. 用两个栈实现队列
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

class CQueue {
    Stack<Integer> st1 ;
    Stack<Integer> st2 ;
    public CQueue() {
        st1 = new Stack<>();
        st2 = new Stack<>();
    }
    
    public void appendTail(int value) {
        st1.push(value);
    }
    
    public int deleteHead() {
        if(st2.isEmpty()){
            while(!st1.isEmpty())
                st2.push(st1.pop());
        }
        if(st2.isEmpty())
        return -1;
       return st2.pop();
    }
}

/**
 * Your CQueue object will be instantiated and called as such:
 * CQueue obj = new CQueue();
 * obj.appendTail(value);
 * int param_2 = obj.deleteHead();
 */

剑指 Offer 32 - III. 从上到下打印二叉树 III
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> nodes = new LinkedList<>();
        List<List<Integer>> ans = new ArrayList<>();
        if(root!=null)
        nodes.add(root);
        while(nodes.size()!=0){
            LinkedList<Integer> tmp = new LinkedList<>();
            for(int i=nodes.size();i>0;i--){
                TreeNode node = nodes.poll();
                if(ans.size()%2==0){
                    tmp.addLast(node.val);
                }else{
                    tmp.addFirst(node.val);
                }
                if(node.left!=null)
                    nodes.add(node.left);
                if(node.right!=null)
                    nodes.add(node.right);
            }
            ans.add(tmp);
        }
        return ans;
    }
}
  1. 螺旋矩阵
    给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。
class Solution {

    int[] dx = {0,1,0,-1};
    int[] dy = {1,0,-1,0};
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> ans = new ArrayList<>();
        int m = matrix.length;
        if(m==0)
        return ans;
        int n = matrix[0].length;
        boolean[][] isVisited = new boolean[m][n];
        int sum = m*n;
        int x = 0;
        int y = 0;
        int index = 1;
        int duration = 0;
        ans.add(matrix[x][y]);
        isVisited[0][0]=true;
        while(index<sum){
            x+=dx[duration];
            y+=dy[duration];
            if(x<0||x>=m||y<0||y>=n||isVisited[x][y]==true){
                x-=dx[duration];
                y-=dy[duration];
                duration=(duration+1)%4;
                x+=dx[duration];
                y+=dy[duration];
            }

            ans.add(matrix[x][y]);
            isVisited[x][y]=true;
            index++;
        }

        return ans;
    }
}
  1. 将每个元素替换为右侧最大元素
    给你一个数组 arr ,请你将每个元素用它右边最大的元素替换,如果是最后一个元素,用 -1 替换。

完成所有替换操作后,请你返回这个数组。

示例:

输入:arr = [17,18,5,4,6,1]
输出:[18,6,6,6,1,-1]

class Solution {
    public int[] replaceElements(int[] arr) {
        int len = arr.length;
        int[] ans = new int[len];
        ans[len-1] = -1;
        int max = arr[len-1];
        for(int i=len-2;i>=0;i--){
            max = Math.max(max,arr[i+1]);
            ans[i] = max;
        }
        return ans;
    }
}
  1. 接雨水
    给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
class Solution {
    public int trap(int[] height) {
        int ans = 0;
        int len = height.length;
        int[] left_max = new int[len];
        int[] right_max = new int[len];
        for(int i=1;i<len;i++){
            left_max[i] = Math.max(left_max[i-1],height[i-1]);
        }
        for(int i=len-2;i>=0;i--){
            right_max[i] = Math.max(right_max[i+1],height[i+1]);
        }
        for(int i=1;i<len-1;i++){
            int left = left_max[i];
            int right = right_max[i];
            int min = Math.min(left,right);
            if(min>height[i])
            ans+=min-height[i];
        }

        return ans;
    }
}
  1. 从前序与中序遍历序列构造二叉树
    根据一棵树的前序遍历与中序遍历构造二叉树。

注意:
你可以假设树中没有重复的元素。

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
       return buildTree(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
    }

    private TreeNode buildTree(int[] preorder,int preStart,int preEnd,int[] inorder,int inStart,int inEnd){
        if(preStart>preEnd)
            return null;
        int value = preorder[preStart];
        TreeNode root = new TreeNode(value);
        int index = 0;
        for(int i=inStart;i<=inEnd;i++){
            if(inorder[i]==value){
                index =i;
                break;
            }
        }
        root.left = buildTree(preorder,preStart+1,preStart+index-inStart,inorder,inStart,index-1);
        root.right = buildTree(preorder,preStart+index-inStart+1,preEnd,inorder,index+1,inEnd);
        return root;
    }
}
  1. 相交链表
    编写一个程序,找到两个单链表相交的起始节点。
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode pointA = headA;
        ListNode pointB = headB;
        while(pointA!=pointB){
            pointA = pointA==null?headB:pointA.next;
            pointB = pointB==null?headA:pointB.next;
        }
        return pointA; 
    }
}
  1. 单词拆分
    给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

说明:

拆分时可以重复使用字典中的单词。
你可以假设字典中没有重复的单词。
示例 1:

输入: s = “leetcode”, wordDict = [“leet”, “code”]
输出: true
解释: 返回 true 因为 “leetcode” 可以被拆分成 “leet code”。
示例 2:

输入: s = “applepenapple”, wordDict = [“apple”, “pen”]
输出: true
解释: 返回 true 因为 “applepenapple” 可以被拆分成 “apple pen apple”。
注意你可以重复使用字典中的单词。
示例 3:

输入: s = “catsandog”, wordDict = [“cats”, “dog”, “sand”, “and”, “cat”]
输出: false

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        Set<String> set = new HashSet<>(wordDict);
        boolean[] dp = new boolean[s.length()+1];
        dp[0] = true;
        for(int i=1;i<=s.length();i++){
            for(int j=0;j<i;j++){
                if(dp[j]&&set.contains(s.substring(j,i))){
                    dp[i]=true;
                    break;
                }
            }
        }
        return dp[s.length()];
    }
}
  1. 二进制求和
    给你两个二进制字符串,返回它们的和(用二进制表示)。

输入为 非空 字符串且只包含数字 1 和 0。

示例 1:

输入: a = “11”, b = “1”
输出: “100”
示例 2:

输入: a = “1010”, b = “1011”
输出: “10101”

class Solution {
    public String addBinary(String a, String b) {
        char[] aa = a.toCharArray();
        char[] bb = b.toCharArray();
        int len1 = aa.length;
        int len2 = bb.length;
        char[] ans = new char[len1+len2];
        int len = len1+len2-1;
        int cf = 0;
        len1--;
        len2--;
        while(len1>=0&&len2>=0){
            int num1 = aa[len1--]-'0';
            int num2 = bb[len2--]-'0';
            int sum = (num1+num2+cf)%2;
            cf = (num1+num2+cf)/2;
            ans[len--]=(char)('0'+sum);
        }
        while(len1>=0){
            int num1 = aa[len1--]-'0';
            int sum = (num1+cf)%2;
            cf = (num1+cf)/2;
            ans[len--]=(char)('0'+sum);
        }
        while(len2>=0){
            int num2 = bb[len2--]-'0';
            int sum = (num2+cf)%2;
            cf = (num2+cf)/2;
            ans[len--]=(char)('0'+sum);
        }

        if(cf>0){
            ans[len--]='1';
        }

        StringBuilder sb = new StringBuilder();
        for(int i=0;i<ans.length;i++){
            if(i==0){
                while(i<ans.length-1&& ans[i]!='1')
                i++;
            }

            sb.append(ans[i]);
        }
        return sb.toString();

    }
}
  1. 二叉搜索树中第K小的元素
    给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。

说明:
你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
  public int kthSmallest(TreeNode root, int k) {
    LinkedList<TreeNode> stack = new LinkedList<TreeNode>();

    while (true) {
      while (root != null) {
        stack.add(root);
        root = root.left;
      }
      root = stack.removeLast();
      if (--k == 0) return root.val;
      root = root.right;
    }
  }
}

  1. 括号生成
    数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
class Solution {
    List<String> ans = new ArrayList<>();
    public List<String> generateParenthesis(int n) {
        String st = "";
        dfs(st,n,0,0);
        return ans;
    }

    private void dfs(String st, int n, int left,int right) {
        if(left==n){
            while(st.length()<2*n){
                st+=")";
            }
            ans.add(new String(st));
            return;
        }
        
        if(left<n){
            dfs(st+"(",n,left+1,right);
        }
        
        if(right<left){
            dfs(st+")",n,left,right+1);
        }
        
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值