byte dance

    技术2022-07-11  108

    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; } } 买卖股票的最佳时机 给定一个数组,它的第 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; } } 三数之和 给你一个包含 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; } } 最小栈 设计一个支持 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:

    /** * 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:

    输入: “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; } } 合并两个有序数组 给你两个有序整数数组 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。

    示例:

    给定有序数组: [-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; } } 二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

    百度百科中最近公共祖先的定义为:“对于有根树 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; } } 搜索旋转排序数组 假设按照升序排序的数组在预先未知的某个点上进行了旋转。

    ( 例如,数组 [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; } } 零钱兑换 给定不同面额的硬币 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->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->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; } } 数组中的第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,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; } } 二叉树的层序遍历 给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。 /** * 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; } } 零钱兑换 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; } } 螺旋矩阵 给定一个包含 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; } } 将每个元素替换为右侧最大元素 给你一个数组 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; } } 接雨水 给定 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; } } 从前序与中序遍历序列构造二叉树 根据一棵树的前序遍历与中序遍历构造二叉树。

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

    例如,给出

    前序遍历 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; } } 相交链表 编写一个程序,找到两个单链表相交的起始节点。 /** * 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; } } 单词拆分 给定一个非空字符串 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 和 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(); } } 二叉搜索树中第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; } } } 括号生成 数字 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); } } }
    Processed: 0.010, SQL: 9