题目495题
提莫攻击
在《英雄联盟》的世界中,有一个叫 “提莫” 的英雄,他的攻击可以让敌方英雄艾希(编者注:寒冰射手)进入中毒状态。现在,给出提莫对艾希的攻击时间序列和提莫攻击的中毒持续时间,你需要输出艾希的中毒状态总时长。
你可以认为提莫在给定的时间点进行攻击,并立即使艾希处于中毒状态。
示例1:
输入: [1,4], 2
输出: 4
原因: 第 1 秒初,提莫开始对艾希进行攻击并使其立即中毒。中毒状态会维持 2 秒钟,直到第 2 秒末结束。
第 4 秒初,提莫再次攻击艾希,使得艾希获得另外 2 秒中毒时间。
所以最终输出 4 秒。
思路
双指针
实现
class Solution { public int findPoisonedDuration(int[] timeSeries, int duration) { int result = 0; int left = 0; int right = 0; for (int time: timeSeries){ if (time >= right){ result += duration; left = time; right = left + duration; } else{ left = time; result = result + duration + left - right; right = left + duration; } } return result; } }
题目496题
下一个更大的元素I
给定两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。
示例 1:
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
思路
单调栈:首先遍历nums2,利用哈希表记录每个元素下一个更大值。然后遍历nums1获取结果
实现
class Solution { public int[] nextGreaterElement(int[] nums1, int[] nums2) { Stack < Integer > stack = new Stack<>(); HashMap < Integer, Integer > map = new HashMap < > (); for(int num: nums2){ while(! stack.empty() && stack.peek()<num){ map.put(stack.pop(), num); } stack.push(num); } while(!stack.empty()){ map.put(stack.pop(),-1); } int[] result = new int[nums1.length]; for(int i = 0; i < nums1.length; i++){ result[i] = map.get(nums1[i]); } return result; } }
题目497题
非重叠矩阵中的随机点
给定一个非重叠轴对齐矩形的列表 rects
,写一个函数 pick
随机均匀地选取矩形覆盖的空间中的整数点。
示例 1:
输入:
["Solution","pick","pick","pick"]
[[[[1,1,5,5]]],[],[],[]]
输出:
[null,[4,1],[4,1],[3,3]]
思路
首先计算所有整数点的总和,然后采用蓄水池抽样,或者二分查找,找到随机点。
实现
import java.util.Random; class Solution { private int[][] rects; private int rectsNum = 0; private List<Integer> rectArray = new ArrayList<>(); public Solution(int[][] rects) { this.rects = rects; for (int[] rect: rects){ rectsNum += (rect[2] - rect[0] + 1)*(rect[3] - rect[1] + 1); rectArray.add(rectsNum); } } public int[] pick() { Random random =new Random(); int randomIndex = random.nextInt(rectsNum); int left = 0; int right = rects.length-1; while(left != right){ int mid = left + (right-left)/2; if(randomIndex >= rectArray.get(mid)){ left = mid +1; } else{ right = mid; } } int rectsIndex = left; int[] rect = rects[rectsIndex]; int length = rect[2] - rect[0] + 1; int high = rect[3] - rect[1] + 1; int lengthIndex = random.nextInt(length); int highIndex = random.nextInt(high); int[] result = new int[2]; result[0] = rect[0] + lengthIndex; result[1] = rect[1] + highIndex; return result; } } /** * Your Solution object will be instantiated and called as such: * Solution obj = new Solution(rects); * int[] param_1 = obj.pick(); */
题目498题
对角线遍历
给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。
思路实现
class Solution { public int[] findDiagonalOrder(int[][] matrix) { if (matrix == null || matrix.length == 0) { return new int[]{}; } int M = matrix.length, N = matrix[0].length; int[] result = new int[M*N]; int row = 0, col = 0; for(int index = 0; index < M*N; index++){ result[index] = matrix[row][col]; int level = row+col; if(level%2==0){ if(col == N-1){ row += 1; } else if(row == 0){ col += 1; } else{ row -= 1; col += 1; } } else{ if(row == M-1){ col += 1; } else if(col == 0){ row += 1; } else{ col -= 1; row += 1; } } } return result; } }
题目500题
键盘行
给定一个单词列表,只返回可以使用在键盘同一行的字母打印出来的单词。键盘如下图所示。
思路实现
class Solution { public String[] findWords(String[] words) { String[] keyboard = new String[]{"QWERTYUIOP", "ASDFGHJKL", "ZXCVBNM"}; HashMap<Character,Integer> lines = new HashMap<>(); for(int index = 0; index <3; index++){ for(char c:keyboard[index].toCharArray()){ c = Character.toUpperCase(c); lines.put(c,index); } } String[] result = new String[words.length]; int count = 0; for(String word: words){ Integer line = -1; boolean temp = true; for(char c:word.toCharArray()){ c = Character.toUpperCase(c); Integer next = lines.get(c); if (line != -1 && next != line){ temp = false; break; } line = next; } if(temp == true){ result[count] = word; count += 1; } } return Arrays.copyOf(result, count); } }
题目501题
二叉搜索树中的重数
给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
思路
中序遍历
实现
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { private List<Integer> answer = new ArrayList<Integer>(); private int cur = 0, count = 0, MaxCount = 0; public int[] findMode(TreeNode root) { dfs(root); int[] result = answer.stream().mapToInt(k->k).toArray(); return result; } private void dfs(TreeNode node){ if (node == null){ return; } dfs(node.left); check(node.val); dfs(node.right); } private void check(int val){ if (val == cur){ count += 1; } else{ count = 1; cur = val; } if(count == MaxCount){ answer.add(val); } else if (count > MaxCount){ MaxCount = count; answer.clear(); answer.add(val); } } }
题目503题
下一个更大元素II
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。
示例 1:
输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数;
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。
思路
与496题相同思路相同,使用栈来解决问题。
首先第一次遍历,得到部分下一个元素更大的结果,此时,栈中保存着一个单调递减的元素索引,其实第一个元素是整个数组的最大元素。遍历0到最大索引,将得到栈中值的结果。
实现
class Solution { public int[] nextGreaterElements(int[] nums) { if(nums.length == 0) { return new int[]{}; } Stack < Integer > stack = new Stack<>(); int[] result = new int[nums.length]; for (int index=0; index<nums.length; index++) { while(!stack.empty() && nums[stack.peek()] < nums[index]) { int tempIndex = stack.pop(); result[tempIndex] = nums[index]; } stack.push(index); } int maxIndex = stack.get(0); int index = 0; while(!stack.empty()) { int numIndex = stack.pop(); while(index <= maxIndex && nums[numIndex] >= nums[index]) { index += 1; } result[numIndex] = nums[numIndex] != nums[maxIndex] ? nums[index]:-1; } return result; } }
题目504题
7进制数
给定一个整数,将其转化为7进制,并以字符串形式输出。
思路实现
class Solution { public String convertToBase7(int num) { char[] digits = new char[]{'0', '1', '2', '3', '4', '5', '6'}; char[] result = new char[33]; boolean sign = (num < 0); if(sign){ num = -num; } int index = 32; while(num>=7) { result[index] = digits[num%7]; num = num/7 ; index -= 1; } result[index] = digits[num]; if(sign) { index -= 1; result[index] = '-'; } return new String(result,index,33-index); } }
题目506题
相对名次
给出 N 名运动员的成绩,找出他们的相对名次并授予前三名对应的奖牌。前三名运动员将会被分别授予 “金牌”,“银牌” 和“ 铜牌”("Gold Medal", "Silver Medal", "Bronze Medal")。
思路实现
class Solution { public String[] findRelativeRanks(int[] nums) { String[] res = new String[nums.length]; HashMap<Integer,Integer> map = new HashMap<Integer,Integer>(); for (int i = 0; i < nums.length; i++) { map.put(nums[i], i); } Arrays.sort(nums); int cur = 0; for (int i = nums.length-1; i >= 0; i--) { if(cur == 0) { res[map.get(nums[i])] = "Gold Medal"; } else if (cur == 1) { res[map.get(nums[i])] = "Silver Medal"; } else if (cur == 2) { res[map.get(nums[i])] = "Bronze Medal"; } else { res[map.get(nums[i])] = Integer.toString(cur+1); } cur +=1; } return res; } }
题目508题
出现次数最多的子树元素和
给你一个二叉树的根结点,请你找出出现次数最多的子树元素和。一个结点的「子树元素和」定义为以该结点为根的二叉树上所有结点的元素之和(包括结点本身)。
你需要返回出现次数最多的子树元素和。如果有多个元素出现的次数相同,返回所有出现次数最多的子树元素和(不限顺序)。
思路
哈希表
实现
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { private HashMap<Integer,Integer> total = new HashMap<Integer,Integer>(); private int maxCount = 0; public int[] findFrequentTreeSum(TreeNode root) { dfs(root); List<Integer> list = new ArrayList<>(); for (Integer key: total.keySet()) { if (total.get(key) == maxCount) { list.add((int)key); } } int[] res = new int[list.size()]; for(int i = 0; i < list.size();i++) { res[i] = list.get(i); } return res; } private int dfs(TreeNode node) { if(node == null) { return 0; } int cur = node.val + dfs(node.left) + dfs(node.right); total.put(cur, total.getOrDefault(cur,0)+1); maxCount = Math.max(maxCount,total.get(cur)); return cur; } }