赞
踩
题目:输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
思路:
class Solution { public String minNumber(int[] nums) { String[] strs = new String[nums.length]; for (int i = 0; i < nums.length; i++) { strs[i] = String.valueOf(nums[i]); } Arrays.sort(strs, (o1, o2) -> (o1 + o2).compareTo(o2 + o1)); StringBuilder sb = new StringBuilder(); for (String str : strs) { sb.append(str); } return sb.toString(); } }
class Solution { public String minNumber(int[] nums) { String[] strs = new String[nums.length]; for(int i = 0; i < nums.length; i++) strs[i] = String.valueOf(nums[i]); quickSort(strs, 0, strs.length - 1); StringBuilder res = new StringBuilder(); for(String s : strs) res.append(s); return res.toString(); } void quickSort(String[] strs, int l, int r) { if(l >= r) return; int i = l, j = r; String tmp = strs[i]; while(i < j) { while((strs[j] + strs[l]).compareTo(strs[l] + strs[j]) >= 0 && i < j) j--; while((strs[i] + strs[l]).compareTo(strs[l] + strs[i]) <= 0 && i < j) i++; tmp = strs[i]; strs[i] = strs[j]; strs[j] = tmp; } strs[i] = strs[l]; strs[l] = tmp; quickSort(strs, l, i - 1); quickSort(strs, i + 1, r); } }
题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
思路:力扣
class Solution { int[] nums, tmp; public int reversePairs(int[] nums) { this.nums = nums; tmp = new int[nums.length]; return mergeSort(0, nums.length - 1); } private int mergeSort(int l, int r) { // 终止条件 if (l >= r) return 0; // 递归划分 int m = (l + r) / 2; int res = mergeSort(l, m) + mergeSort(m + 1, r); // 合并阶段 int i = l, j = m + 1; for (int k = l; k <= r; k++) tmp[k] = nums[k]; for (int k = l; k <= r; k++) { if (i == m + 1) nums[k] = tmp[j++]; else if (j == r + 1 || tmp[i] <= tmp[j]) nums[k] = tmp[i++]; else { nums[k] = tmp[j++]; res += m - i + 1; // 统计逆序对 } } return res; } }
题目:给定一个整数数组,编写一个函数,找出索引
m
和n
,只要将索引区间[m,n]
的元素排好序,整个数组就是有序的。注意:n-m
尽量最小,也就是说,找出符合条件的最短序列。函数返回值为[m,n]
,若不存在这样的m
和n
(例如整个数组是有序的),请返回[-1,-1]
。
class Solution { public int[] subSort(int[] array) { int N = array.length, start = -1, end = -1; int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE; // 从前往后找目标末位,使得从该位到最后,数组保持递增 for (int i = 0; i < N; i++) { if (array[i] >= max) max = array[i]; else end = i; } // 数组恒递增,说明数组是有序的,直接返回 if (end == -1) return new int[] {-1, -1}; // 从后往前找目标首位,使得从该位到最前,数组保持递减 for (int i = end; i >= 0; i--) { if (array[i] <= min) min = array[i]; else start = i; } return new int[] {start, end}; } }
题目:
n
个孩子站成一排。给你一个整数数组ratings
表示每个孩子的评分。你需要按照以下要求,给这些孩子分发糖果:
- 每个孩子至少分配到
1
个糖果。- 相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。
class Solution { public int candy(int[] ratings) { if(ratings == null || ratings.length == 0){ return 0; } int[] nums = new int[ratings.length];//记录每一位孩子得到的糖果数 nums[0] = 1; //先正序遍历,如果后一位比前一位高分,就给比前一位多1的糖果,否则给1 for(int i = 1; i < ratings.length; i++){ if(ratings[i] > ratings[i-1]){ nums[i] = nums[i-1] + 1; }else { nums[i] = 1; } } //在倒叙遍历,如果前一位比后一位高分并且得到的糖果小于或等于后一位,就给前一位孩子比后一位孩子多一个糖果 for(int i = ratings.length -2 ; i >= 0; i--){ if(ratings[i] > ratings[i+1] && nums[i] <= nums[i+1]){ nums[i] = nums[i+1] +1; } } int count = 0; for(int i : nums){ count +=i; } return count; } }
题目:给你一个字符串
s
和一个字符串列表wordDict
作为字典。请你判断是否可以利用字典中出现的单词拼接出s
。
class Solution { public boolean wordBreak(String s, List<String> wordDict) { int n = s.length(); boolean[] dp = new boolean[n + 1]; // 初始化 dp[0] = true; for(int i=1;i<=n;i++){ for(int j=0;j<i;j++){ // 右半部分存在于单词字典中 String word = s.substring(j,i); // 左半部分由dp递推得到 if(wordDict.contains(word) && dp[j]){ dp[i] = true; } } } return dp[n]; } }
题目:给定一个数组
nums
,编写一个函数将所有0
移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。思路:从左边开始找到第一个0的位置,从右边开始找到第一个不为0的位置,交换元素。
class Solution { public void moveZeroes(int[] nums) { int left = 0; int right = 0; int start = 0; int count = 0; for (int i = 0; i < nums.length; i++) { if (nums[i] != 0) { count++; } } if (count != nums.length) { while (true) { for (int i = 0; i < nums.length; i++) { if (nums[i] == 0) { left = i; break; } } for (int i = start; i < nums.length; i++) { if (nums[i] != 0) { right = i; break; } } if (left < right) { int temp = nums[right]; nums[right] = nums[left]; nums[left] = temp; } start++; int finish_left = 0; int finish_right = 0; for (int i = 0; i < nums.length; i++) { if (nums[i] == 0) { finish_left = i; break; } } for (int i = 0; i < nums.length; i++) { if (nums[i] != 0) { finish_right = i; } } if (finish_right <= finish_left) { break; } } } } }
题目:给定一个二进制数组
nums
, 找到含有相同数量的0
和1
的最长连续子数组,并返回该子数组的长度。思路:将0变为-1,当遍历前缀和出现同样元素a时,说明第一个a到第二个a中间的0,1数目相同。
class Solution { public int findMaxLength(int[] nums) { /** 将数组中的0换成-1, 求和为0的最长子数组 转换成前缀和问题 */ for(int i = 0; i < nums.length; ++i){ if(nums[i] == 0) nums[i] = -1; } Map<Integer, Integer> map = new HashMap<>(); map.put(0, -1); int ans = 0, sum = 0; for(int i = 0; i < nums.length; ++i){ sum += nums[i]; if(map.containsKey(sum)){ ans = Math.max(ans, i - map.get(sum)); }else map.put(sum, i); } return ans; } }
题目:环形公交路线上有 n 个站,按次序从 0 到 n - 1 进行编号。我们已知每一对相邻公交站之间的距离,distance[i] 表示编号为 i 的车站和编号为 (i + 1) % n 的车站之间的距离。环线上的公交车都可以按顺时针和逆时针的方向行驶。返回乘客从出发点 start 到目的地 destination 之间的最短距离。
class Solution { public int distanceBetweenBusStops(int[] distance, int start1, int destination1) { int sum1 = 0; int sum2 = 0; int start = Math.min(start1, destination1); int destination = Math.max(start1, destination1); for (int i = start; i < destination; i++) { sum1 += distance[i]; } for (int i = start-1; i >= 0; i--) { sum2 += distance[i]; } for (int i = distance.length - 1; i >= destination; i--) { sum2 += distance[i]; } return Math.min(sum1, sum2); } }
题目:给你一个整数数组 arr ,请你将数组中的每个元素替换为它们排序后的序号。序号代表了一个元素有多大。序号编号的规则如下:
- 序号从 1 开始编号。一个元素越大,那么序号越大。
- 如果两个元素相等,那么它们的序号相同。
- 每个数字的序号都应该尽可能地小。
class Solution { public int[] arrayRankTransform(int[] arr) { if (arr.length == 0) { return new int[]{}; } int[] c = arr.clone(); int[] result = new int[c.length]; int x = 0; Arrays.sort(c); int index = 1; HashMap<Integer, Integer> b = new HashMap(); for (int j = 0; j < c.length; j++) { if (!b.containsKey(c[j])) { b.put(c[j], index); index++; } } ArrayList<Integer> a = new ArrayList(); for (int i = 0; i < arr.length; i++) { result[i] = b.get(arr[i]); } return result; } }
题目:给你一个数组 nums ,它包含 n 个正整数。你需要计算所有非空连续子数组的和,并将它们按升序排序,得到一个新的包含 n * (n + 1) / 2 个数字的数组。
请你返回在新数组中下标为 left 到 right (下标从 1 开始)的所有数字和(包括左右端点)。由于答案可能很大,请你将它对 10^9 + 7 取模后返回。
class Solution { public int rangeSum(int[] nums, int n, int left, int right) { int length = (1 + n) * n / 2; final int MOD = 1000000000 + 7; int[] result = new int[length]; result = continuousSubList(nums, length); Arrays.sort(result); long sum = 0; for (int i = left - 1; i < right; i++) { sum += result[i]; } return (int) (sum % MOD); } public int[] continuousSubList(int[] arr, int length) { int[] result = new int[length]; List<Integer> resultList = new ArrayList<>(); if (arr == null || arr.length < 1) { return null; } // 对于每个位置都求包含他本身在内的所有连续子数组 for (int i = 0; i < arr.length; i++) { for (int j = i; j < arr.length; j++) { // 从 i ~ j位置求得一个子数组 int temp = 0; for (int k = i; k <= j; k++) { temp += arr[k]; } resultList.add(temp); } } for (int i = 0; i < length; i++) { result[i] = resultList.get(i); } // 返回最终结果 return result; } }
题目:给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。子数组 定义为原数组中的一个连续子序列。请你返回 arr 中 所有奇数长度子数组的和 。
输入:arr = [1,4,2,5,3] 输出:58 解释:所有奇数长度子数组和它们的和为: [1] = 1 [4] = 4 [2] = 2 [5] = 5 [3] = 3 [1,4,2] = 7 [4,2,5] = 11 [2,5,3] = 10 [1,4,2,5,3] = 15 我们将所有值求和得到 1 + 4 + 2 + 5 + 3 + 7 + 11 + 10 + 15 = 58
class Solution { public int sumOddLengthSubarrays(int[] arr) { int result = 0; for (int i = 1; i <= arr.length; i += 2) { int temp = 0; for (int j = 0; j <= arr.length - i; j++) { for (int k = 0; k < i; k++) { temp += arr[j+k]; } } result+=temp; } return result; } }
题目:给你一个 升序排列 的数组
nums
,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。提示:一项一项删除会超时。
class Solution { public int removeDuplicates(int[] nums) { if (nums.length == 1) { return 1; } Set s = new HashSet(); for (int i = 0; i < nums.length; i++) { s.add(nums[i]); } int temp = s.size(); int q = 0; for (int i = 0; i < nums.length && q < temp; i++) { int start = 0; for (int j = i; j < nums.length - 1; j++) { if (nums[j] == nums[j + 1]) { start++; } else { break; } } for (int j = i + 1; j < nums.length - start; j++) { nums[j] = nums[j + start]; } q++; } return q; } }
题目:给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
class Solution { public void rotate(int[][] matrix) { int n = matrix.length - 1; for (int i = 0; i < matrix.length / 2; i++) { for (int j = i; j < n - i; j++) { // 获取各顶点的值 int a = matrix[i][j]; // 左上角 int b = matrix[j][n - i]; // 右上角 int c = matrix[n - i][n - j]; // 右下角 int d = matrix[n - j][i]; // 左下角 // 交换各顶点的值 matrix[i][j] = d; // 左上角 matrix[j][n - i] = a; // 右上角 matrix[n - i][n - j] = b; // 右下角 matrix[n - j][i] = c; // 左下角 } } } }
题目:给你一个
m
行n
列的矩阵matrix
,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。思路1:有限制,需要找到一个原本数组不存在的数。
class Solution { public List<Integer> spiralOrder(int[][] matrix) { List result = new ArrayList(); int maxNum = matrix.length * matrix[0].length; int curNum = 1; int row = 0, column = 0; int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 右下左上 int directionIndex = 0; while (curNum <= maxNum) { result.add(matrix[row][column]); matrix[row][column] = 0; curNum++; int nextRow = row + directions[directionIndex][0], nextColumn = column + directions[directionIndex][1]; if (nextRow < 0 || nextRow >= matrix.length || nextColumn < 0 || nextColumn >= matrix[0].length || matrix[nextRow][nextColumn] == 0) { directionIndex = (directionIndex + 1) % 4; // 顺时针旋转至下一个方向 } row = row + directions[directionIndex][0]; column = column + directions[directionIndex][1]; } return result; } }思路2:按层模拟。
class Solution { public int[] spiralOrder(int[][] matrix) { //边界条件判断 if(matrix == null || matrix.length == 0 || matrix[0].length == 0){ return new int[0]; } int m = matrix.length,n = matrix[0].length; int num = 0; int[] arr = new int[m*n]; int left = 0,right = n - 1; int up = 0,down = m - 1; while(num < m * n){ //最上面一行 for(int i = left;i <= right && num < m * n;i++){ arr[num++] = matrix[up][i]; } up++; //最右边一列 for(int i = up;i <= down && num < m * n;i++){ arr[num++] = matrix[i][right]; } right--; //最下面一行 for(int i = right;i >= left && num < m * n;i--){ arr[num++] = matrix[down][i]; } down--; //最左边一列 for(int i = down;i >= up && num < m * n;i--){ arr[num++] = matrix[i][left]; } left++; } return arr; } }
题目:给你一个正整数
n
,生成一个包含1
到n2
所有元素,且元素按顺时针顺序螺旋排列的n x n
正方形矩阵matrix
。
class Solution { public int[][] generateMatrix(int n) { int maxNum = n * n; int curNum = 1; int[][] matrix = new int[n][n]; int row = 0, column = 0; int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 右下左上 int directionIndex = 0; while (curNum <= maxNum) { matrix[row][column] = curNum; curNum++; int nextRow = row + directions[directionIndex][0], nextColumn = column + directions[directionIndex][1]; if (nextRow < 0 || nextRow >= n || nextColumn < 0 || nextColumn >= n || matrix[nextRow][nextColumn] != 0) { directionIndex = (directionIndex + 1) % 4; // 顺时针旋转至下一个方向 } row = row + directions[directionIndex][0]; column = column + directions[directionIndex][1]; } return matrix; } }
题目:给你一个数组,将数组中的元素向右轮转
k
个位置,其中k
是非负数。
class Solution { public void rotate(int[] nums, int k) { int newNums[] = nums.clone(); for (int i = 0; i < newNums.length; i++) { nums[k % nums.length] = newNums[i]; k++; } } }
题目:用一个大小为
m x n
的二维网格grid
表示一个箱子。你有n
颗球。箱子的顶部和底部都是开着的。箱子中的每个单元格都有一个对角线挡板,跨过单元格的两个角,可以将球导向左侧或者右侧。
- 将球导向右侧的挡板跨过左上角和右下角,在网格中用
1
表示。- 将球导向左侧的挡板跨过右上角和左下角,在网格中用
-1
表示。在箱子每一列的顶端各放一颗球。每颗球都可能卡在箱子里或从底部掉出来。如果球恰好卡在两块挡板之间的 "V" 形图案,或者被一块挡导向到箱子的任意一侧边上,就会卡住。返回一个大小为
n
的数组answer
,其中answer[i]
是球放在顶部的第i
列后从底部掉出来的那一列对应的下标,如果球卡在盒子里,则返回-1
。
class Solution { public int[] findBall(int[][] grid) { int hight = grid.length; int weight = grid[0].length; int[] result = new int[weight]; for (int i = 0; i < weight; i++) { result[i] = i; } for (int i = 0; i < hight; i++) { for (int j = 0; j < weight; j++) { if (result[j] != -1 && grid[i][result[j]] == 1) { if (result[j] < weight - 1 && grid[i][result[j] + 1] == -1) { result[j] = -1; } else { result[j] += 1; } } else if (result[j] != -1 && grid[i][result[j]] == -1) { if (result[j] > 0 && grid[i][result[j] - 1] == 1) { result[j] = -1; } else { result[j] -= 1; } } if (result[j] > weight - 1 || result[j] < 0) { result[j] = -1; continue; } } } return result; } }
题目:给你两个大小为 n x n 的二进制矩阵 mat 和 target 。现 以 90 度顺时针轮转 矩阵 mat 中的元素 若干次 ,如果能够使 mat 与 target 一致,返回 true ;否则,返回 false 。
class Solution { public boolean findRotation(int[][] matrix, int[][] target) { for (int i = 0; i < 4; i++) { boolean flag = rotate(matrix, target); if (flag == true) { return true; } } return false; } public boolean rotate(int[][] matrix, int[][] target) { int n = matrix.length - 1; for (int i = 0; i < matrix.length / 2; i++) { for (int j = i; j < n - i; j++) { // 获取各顶点的值 int a = matrix[i][j]; // 左上角 int b = matrix[j][n - i]; // 右上角 int c = matrix[n - i][n - j]; // 右下角 int d = matrix[n - j][i]; // 左下角 // 交换各顶点的值 matrix[i][j] = d; // 左上角 matrix[j][n - i] = a; // 右上角 matrix[n - i][n - j] = b; // 右下角 matrix[n - j][i] = c; // 左下角 } } for (int i=0;i<matrix.length;i++){ for (int j=0;j<matrix[0].length;j++){ if (matrix[i][j]!=target[i][j]){ return false; } } } return true; } }
题目:给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。说明:你不能倾斜容器。
思路:初始底最大,然后缩短,比较两边高,修改低边。
class Solution { public int maxArea(int[] height) { int left = 0; int right = height.length - 1; int area = 0; while (left < right) { area = Math.max(Math.min(height[left], height[right]) * (right - left), area); if (height[left] < height[right]) { left++; } else { right--; } } return area; } }
题目:给定
n
个非负整数表示每个宽度为1
的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。思路:双指针
class Solution { public int trap(int[] height) { int ans = 0; int left = 0, right = height.length - 1; int leftMax = 0, rightMax = 0; while (left < right) { leftMax = Math.max(leftMax, height[left]); rightMax = Math.max(rightMax, height[right]); if (height[left] < height[right]) { ans += leftMax - height[left]; ++left; } else { ans += rightMax - height[right]; --right; } } return ans; } }
题目:给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。
思路:中心发散
class Solution { public int largestRectangleArea(int[] heights) { if (heights.length == 1) { return heights[0]; } int area = 0; for (int i = 0; i < heights.length; i++) { if (i != 0 && heights[i] == heights[i - 1]) { continue; } int left = i; int right = i; while (left > 0 && heights[i] <= heights[left - 1]) { left--; } while (right < heights.length - 1 && heights[i] <= heights[right + 1]) { right++; } area = Math.max(area, (right - left + 1) * heights[i]); } return area; } }
题目:以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
class Solution { public int[][] merge(int[][] intervals) { int n = intervals.length; if (n == 0) { return null; } //先按起点升序,再按终点降序 Arrays.sort(intervals, (o1, o2) -> o1[0] == o2[0] ? o2[1] - o1[1] : o1[0] - o2[0]); List<int[]> res = new ArrayList<>(); int left = intervals[0][0]; int right = intervals[0][1]; for (int i = 1; i < n; i++) { if (intervals[i][0] > right) { //无交集 res.add(new int[]{left, right}); left = intervals[i][0]; right = intervals[i][1]; } else if (intervals[i][1] < right) { //被覆盖 } else if (intervals[i][1] >= right && intervals[i][0] <= right) { //相交 right = intervals[i][1]; } } res.add(new int[]{left, right}); return res.toArray(new int[0][]); } }
题目:给你一个 无重叠的 ,按照区间起始端点排序的区间列表。在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
思路:不采用规则判断是因为过于麻烦,而且需要考虑横跨多个区间的问题。
class Solution { public int[][] insert(int[][] intervals, int[] newInterval) { int n = intervals.length; int[][] temp = new int[n + 1][2]; for (int i = 0; i < n; i++) { temp[i] = intervals[i]; } temp[n] = newInterval; Arrays.sort(temp, (o1, o2) -> o1[0] == o2[0] ? o2[1] - o1[1] : o1[0] - o2[0]); //先按起点升序,再按终点降序 List<int[]> res = new ArrayList<>(); int left = temp[0][0]; int right = temp[0][1]; for (int i = 0; i <= n; i++) { if (temp[i][0] > right) { //无交集 res.add(new int[]{left, right}); left = temp[i][0]; right = temp[i][1]; } else if (temp[i][1] < right) { //被覆盖 } else if (temp[i][1] >= right && temp[i][0] <= right) { //相交 right = temp[i][1]; } } res.add(new int[]{left, right}); return res.toArray(new int[0][]); } }
题目:城市的 天际线 是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。给你所有建筑物的位置和高度,请返回 由这些建筑物形成的 天际线 。每个建筑物的几何信息由数组
buildings
表示,其中三元组buildings[i] = [lefti, righti, heighti]
表示:
lefti
是第i
座建筑物左边缘的x
坐标。righti
是第i
座建筑物右边缘的x
坐标。heighti
是第i
座建筑物的高度。你可以假设所有的建筑都是完美的长方形,在高度为
0
的绝对平坦的表面上。
// 把每栋房子看作矩形,首先把矩形(Li,-Hi)和(Ri,Hi)插入到multiset st中,自动排序 // 遍历multiset st,同时用另一个multiset height保存当前位置左边的历史高度,height.rbegin()即其最大值 // 遍历过程中,如果发现是Li,则插入到height,否则是Ri,删除Ri在height中对应的Li // 如果height的最大值发生了变化,则该i元素就是返回结果之一 class Solution { public List<List<Integer>> getSkyline(int[][] buildings) { PriorityQueue<int[]> pq = new PriorityQueue<int[]>((a, b) -> b[1] - a[1]); List<Integer> boundaries = new ArrayList<Integer>(); for (int[] building : buildings) { boundaries.add(building[0]); boundaries.add(building[1]); } Collections.sort(boundaries); List<List<Integer>> ret = new ArrayList<List<Integer>>(); int n = buildings.length, idx = 0; for (int boundary : boundaries) { while (idx < n && buildings[idx][0] <= boundary) { pq.offer(new int[]{buildings[idx][1], buildings[idx][2]}); idx++; } while (!pq.isEmpty() && pq.peek()[0] <= boundary) { pq.poll(); } int maxn = pq.isEmpty() ? 0 : pq.peek()[1]; if (ret.size() == 0 || maxn != ret.get(ret.size() - 1).get(1)) { ret.add(Arrays.asList(boundary, maxn)); } } return ret; } }
题目:给定一个 无重复元素 的 有序 整数数组
nums
。返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums
的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于nums
的数字x
。列表中的每个区间范围[a,b]
应该按如下格式输出:
"a->b"
,如果a != b
"a"
,如果a == b
class Solution { public List<String> summaryRanges(int[] nums) { ArrayList<String> result = new ArrayList<String>(); if (nums.length == 0) { return result; } int index = 0; int temp = nums[index]; int length = nums.length; for (int i = 1; i < length; i++) { if (nums[i] - nums[i - 1] == 1) { } else { if (nums[index] == nums[i - 1]) { result.add(nums[index] + ""); } else { result.add(nums[index] + "->" + nums[i - 1]); } index = i; } } if (nums[index] == nums[length - 1]) { result.add(nums[index] + ""); } else { result.add(nums[index] + "->" + nums[length - 1]); } return result; } }
题目:给定两个数组
nums1
和nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
class Solution { public int[] intersection(int[] nums1, int[] nums2) { Arrays.sort(nums1); Arrays.sort(nums2); ArrayList<Integer> arrayList = new ArrayList(); int left = 0; int right = 0; while (left < nums1.length && right < nums2.length) { if (nums1[left] == nums2[right]) { if (!arrayList.contains(nums1[left])){ arrayList.add(nums1[left]); } left++; right++; } else if (nums1[left] > nums2[right]) { right++; } else { left++; } } int[] result = new int[arrayList.size()]; for (int i = 0; i < result.length; i++) { result[i] = arrayList.get(i); } return result; } }
题目:给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。
class Solution { public int[] intersect(int[] nums1, int[] nums2) { int length1 = nums1.length; int length2 = nums2.length; ArrayList<Integer> a = new ArrayList(); if (length1 > length2) { for (int i = 0; i < length2; i++) { for (int j = 0; j < length1; j++) { if (nums2[i] == nums1[j]) { a.add(nums2[i]); nums1[j] = -1; break; } } } } else { for (int i = 0; i < length1; i++) { for (int j = 0; j < length2; j++) { if (nums1[i] == nums2[j]) { a.add(nums1[i]); nums2[j] = -1; break; } } } } int result[] = new int[a.size()]; for (int i = 0; i < a.size(); i++) { result[i] = a.get(i); } return result; } }
题目:给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。
思路:升序排列,然后如果最小的有区间大于下一个的左端,说明相交,剔除下一区间(因为下一区间的右端大于该区间的右端),如果小于,说明不相交,右端换为新右端。
class Solution { public int eraseOverlapIntervals(int[][] intervals) { Arrays.sort(intervals, (o1, o2) -> Integer.compare(o1[1], o2[1])); int cur = intervals[0][1]; int res = 0; for (int i = 1; i < intervals.length; i++) { if (cur > intervals[i][0]) { res++; } else { cur = intervals[i][1]; } } return res; } }
题目:有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组
points
,其中points[i] = [xstart, xend]
表示水平直径在xstart
和xend
之间的气球。你不知道气球的确切 y 坐标。一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标
x
处射出一支箭,若有一个气球的直径的开始和结束坐标为x
start
,x
end
, 且满足xstart ≤ x ≤ x
end
,则该气球会被 引爆 。可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。给你一个数组
points
,返回引爆所有气球所必须射出的 最小 弓箭数 。
class Solution { public int findMinArrowShots(int[][] points) { if (points.length == 0) { return 0; } Arrays.sort(points, new Comparator<int[]>() { public int compare(int[] point1, int[] point2) { if (point1[1] > point2[1]) { return 1; } else if (point1[1] < point2[1]) { return -1; } else { return 0; } } }); int pos = points[0][1]; int ans = 1; for (int[] balloon: points) { if (balloon[0] > pos) { pos = balloon[1]; ++ans; } } return ans; } }
题目:实现一个 MyCalendar 类来存放你的日程安排。如果要添加的日程安排不会造成 重复预订 ,则可以存储这个新的日程安排。
当两个日程安排有一些时间上的交叉时(例如两个日程安排都在同一时间内),就会产生 重复预订 。日程可以用一对整数 start 和 end 表示,这里的时间是半开区间,即 [start, end), 实数 x 的范围为, start <= x < end 。
实现 MyCalendar 类:
- MyCalendar() 初始化日历对象。
- boolean book(int start, int end) 如果可以将日程安排成功添加到日历中而不会导致重复预订,返回 true 。否则,返回 false 并且不要将该日程安排添加到日历中。
class MyCalendar { List<int[]> booked; public MyCalendar() { booked = new ArrayList<int[]>(); } public boolean book(int start, int end) { for (int[] arr : booked) { int l = arr[0], r = arr[1]; if (l < end && start < r) { return false; } } booked.add(new int[]{start, end}); return true; } }
题目:给定两个由一些 闭区间 组成的列表,firstList 和 secondList ,其中 firstList[i] = [starti, endi] 而 secondList[j] = [startj, endj] 。每个区间列表都是成对 不相交 的,并且 已经排序 。
返回这 两个区间列表的交集 。形式上,闭区间 [a, b](其中 a <= b)表示实数 x 的集合,而 a <= x <= b 。两个闭区间的 交集 是一组实数,要么为空集,要么为闭区间。例如,[1, 3] 和 [2, 4] 的交集为 [2, 3] 。
class Solution { public int[][] intervalIntersection(int[][] firstList, int[][] secondList) { ArrayList<int[]> arrayList = new ArrayList(); int left = 0; int right = 0; while (left < firstList.length && right < secondList.length) { int a = firstList[left][0]; int b = firstList[left][1]; int c = secondList[right][0]; int d = secondList[right][1]; if (a < c && b > d) { arrayList.add(new int[]{c, d}); right++; } else if (c < a && d > b) { arrayList.add(new int[]{a, b}); left++; } else if (a <= c && b <= d && b > c) { arrayList.add(new int[]{c, b}); left++; } else if (c <= a && d <= b && a < d) { arrayList.add(new int[]{a, d}); right++; } else if (a <= c && b <= d && b < c) { left++; } else if (c <= a && d <= b && a > d) { right++; } else if (b == c) { arrayList.add(new int[]{b, c}); left++; } else if (a == d) { arrayList.add(new int[]{a, d}); right++; } } return arrayList.toArray(new int[arrayList.size()][]); } }
题目:给定一个整数数组
nums
和一个整数目标值target
,请你在该数组中找出 和为目标值target
的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。
class Solution { public int[] twoSum(int[] nums, int target) { HashMap<Integer,Integer> map = new HashMap<>(); for(int i = 0; i < nums.length; i++){ if(map.containsKey(nums[i])){ return new int[]{map.get(nums[i]), i}; } map.put(target - nums[i], i); } return null; } }
题目:设计一个算法,找出数组中两数之和为指定值的所有整数对。一个数只能属于一个数对。
思路1:HashMap,把出现过的元素当成key,元素出现的次数当成value存到map中,如果遍历到某一个元素num,查看target - num元素是否出现过,如果出现过,那么可以组成一个整数对,注意这里一个数只能属于一个数对,所以判断target - num元素出现的次数,如果为1,直接remove即可,否则更新target - num元素出现的次数-1。
class Solution { public List<List<Integer>> pairSums(int[] nums, int target) { //key:数组的元素;value:该元素出现的次数 Map<Integer, Integer> map = new HashMap<>(); List<List<Integer>> ans = new ArrayList<>(); for (int num : nums) { Integer count = map.get(target - num); if (count != null) { ans.add(Arrays.asList(num, target - num)); if (count == 1) map.remove(target - num); else map.put(target - num, --count); } else map.put(num, map.getOrDefault(num, 0) + 1); } return ans; } }思路2:使用双指针实现,注意要先对数组进行排序处理。
class Solution { public List<List<Integer>> pairSums(int[] nums, int target) { //对数组进行排序 Arrays.sort(nums); List<List<Integer>> ans = new LinkedList<>(); int left = 0, right = nums.length - 1; while (left < right) { //两个指针所指的两个元素和 int sum = nums[left] + nums[right]; //如果两个的和小于目标值,那么left指针向右走一步继续寻找 if (sum < target) ++left; //如果两个的和大于目标值,那么right指针向左走一步继续寻找 else if (sum > target) --right; //如果刚好等于要找的target值,那么加入结果集中,并且left指针和right指针分别向右和向左走一步(因为一个数只能属于一个数对) else ans.add(Arrays.asList(nums[left++], nums[right--])); } return ans; } }
题目:给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。注意:答案中不可以包含重复的三元组。
思路:遍历数组每个元素,利用-c=a+b,其中a,b为双指针,根据大小移动。
class Solution { public List<List<Integer>> threeSum(int[] nums) {// 总时间复杂度:O(n^2) List<List<Integer>> ans = new ArrayList<>(); if (nums == null || nums.length <= 2) return ans; Arrays.sort(nums); // O(nlogn) for (int i = 0; i < nums.length - 2; i++) { // O(n^2) if (nums[i] > 0) break; // 第一个数大于 0,后面的数都比它大,肯定不成立了 if (i > 0 && nums[i] == nums[i - 1]) continue; // 去掉重复情况 int target = -nums[i]; int left = i + 1, right = nums.length - 1; while (left < right) { if (nums[left] + nums[right] == target) { ans.add(new ArrayList<>(Arrays.asList(nums[i], nums[left], nums[right]))); // 现在要增加 left,减小 right,但是不能重复,比如: [-2, -1, -1, -1, 3, 3, 3], i = -2, left = 1, right = 6, [-2, -1, 3] 的答案加入后,需要排除重复的 -1 和 3 left++; right--; // 首先无论如何先要进行加减操作 while (left < right && nums[left] == nums[left - 1]) left++; while (left < right && nums[right] == nums[right + 1]) right--; } else if (nums[left] + nums[right] < target) { left++; } else { // nums[left] + nums[right] > target right--; } } } return ans; } }
题目:给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在恰好一个解。
思路:排序,然后遍历(双指针,减少复杂度)。
class Solution { public int threeSumClosest(int[] nums, int target) { Arrays.sort(nums); int result = Integer.MAX_VALUE; int f = 0; for (int i = 0; i < nums.length - 2; i++) { int left = i + 1; int right = nums.length - 1; while (left < right) { int temp = nums[i] + nums[left] + nums[right]; if (result > Math.abs(target - temp)) { result = Math.abs(target - temp); f = temp; } if (temp > target) { right--; } else if (temp < target) { left++; } else { return target; } } } return f; } }
题目:给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
class Solution { public List<List<Integer>> fourSum(int[] nums, int a) { List<List<Integer>> ans = new ArrayList<>(); if (nums == null || nums.length <= 2) return ans; Arrays.sort(nums); // O(nlogn) long target = a; for (int i = 0; i < nums.length - 3; i++) { // O(n^2) if (i > 0 && nums[i] == nums[i - 1]) continue; // 去掉重复情况 for (int j = i + 1; j < nums.length - 2; j++) { if (j > i + 1 && nums[j] == nums[j - 1]) continue; long newtarget = target - nums[i] - nums[j]; int left = j + 1, right = nums.length - 1; while (left < right) { int cur = nums[left] + nums[right]; if (cur == newtarget) { ans.add(new ArrayList<>(Arrays.asList(nums[i], nums[j], nums[left], nums[right]))); while (left < right && nums[left] == nums[left + 1]) left++; while (left < right && nums[right] == nums[right - 1]) right--; left++; right--; // 首先无论如何先要进行加减操作 } else if (cur < newtarget) { left++; } else { right--; } } } } return ans; } }
题目:给你一个整数数组
nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组 是数组中的一个连续部分。思路1:对于含有正数的序列而言,最大子序列肯定是正数,所以头尾肯定都是正数,我们可以从第一个正数开始算起,每往后加一个数便更新一次和的最大值;当当前和成为负数时,则表明此前序列无法为后面提供最大子序列和,因此必须重新确定序列首项。
class Solution { public int maxSubArray(int[] nums) { int res = nums[0]; int sum = 0; for (int num : nums) { if (sum > 0) sum += num; else sum = num; res = Math.max(res, sum); } return res; } }思路2:动态规划
class Solution { public int maxSubArray(int[] nums) { int m = nums[0]; for (int i = 1; i < nums.length; i++) { nums[i] = Math.max(nums[i], nums[i] + nums[i - 1]); m = Math.max(m, nums[i]); } return m; } }
题目:输入一个正整数
target
,输出所有和为target
的连续正整数序列(至少含有两个数)。序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
class Solution { public int[][] findContinuousSequence(int target) { //思路,双指针 //刚开始 left 在位置 1, right 在位置 2, 定义左右指针之间的数字和为 sum = n*(a1+an)/2 //1.类似二分查找的逻辑,当 sum 等于 target 时,将左右指针之间的这种数组加入结果,然后左指针右移 //2.当 sum 小于 target 时,右指针右移增大 sum //3.当 sum 大于 target 时,说明以 left 为起点组成的数组不符要求,左指针右移 //创建结果数组 List<int[]> list = new ArrayList<>(); int left = 1; int right = 2; //终止条件是左指针移动到右指针位置,说明此时已经不存在两个数之和能小于 target 了 while (left < right) { int sum = (right - left + 1) * (left + right) / 2; if (sum == target) { //创建数组存储左右指针之间的数组组合 int[] tmp = new int[right - left + 1]; for (int i = 0; i < right - left + 1; i++) { tmp[i] = left + i; } //将临时数组结果存储入List list.add(tmp); //继续探索下一种方案 ++left; }else if (sum<target){ ++right; }else { ++left; } } //掌握此种二维list转数组方法 return list.toArray(new int[list.size()][]); } }
题目:给定两个整数数组,请交换一对数值(每个数组中取一个数值),使得两个数组所有元素的和相等。返回一个数组,第一个元素是第一个数组中要交换的元素,第二个元素是第二个数组中要交换的元素。若有多个答案,返回任意一个均可。若无满足条件的数值,返回空数组。
思路:A-B=diff,A-diff/2=B+diff/2;
class Solution { public int[] findSwapValues(int[] array1, int[] array2) { int sum1 = 0, sum2 = 0; for (int num : array1) { sum1 += num; } for (int num : array2) { sum2 += num; } int diff = sum1 - sum2; if (diff % 2 != 0) { // 如果两个数组的总和之差为奇数,则不可能找到符合条件的数值 return new int[0]; } diff /= 2; // 将差值除以2,这样就可以在第二个数组中找到一个数值,使得交换后两个数组的总和相等 Set<Integer> set = new HashSet<>(); for (int num : array2) { set.add(num); } for (int num : array1) { if (set.contains(num - diff)) { return new int[]{num, num - diff}; } } return new int[0]; } }
题目:给你一个整数数组
nums
,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。测试用例的答案是一个 32-位 整数。子数组 是数组的连续子序列。思路:求最大值,可以看成求被0拆分的各个子数组的最大值。当一个数组中没有0存在,则分为两种情况:
- 负数为偶数个,则整个数组的各个值相乘为最大值;
- 负数为奇数个,则从左边开始,乘到最后一个负数停止有一个“最大值”,从右边也有一个“最大值”,比较,得出最大值。
class Solution { public int maxProduct(int[] nums) { int a=1; int max=nums[0]; for(int num:nums){ a=a*num; if(max<a)max=a; if(num==0)a=1; } a=1; for(int i=nums.length-1;i>=0;i--){ a=a*nums[i]; if(max<a)max=a; if(nums[i]==0)a=1; } return max; } }
题目:给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。你所设计的解决方案必须只使用常量级的额外空间。
class Solution { public int[] twoSum(int[] numbers, int target) { int left = 0; int right = numbers.length-1; while (left < right) { int sum = numbers[left] + numbers[right]; if (sum == target) { return new int[]{left+1, right+1}; } else if (sum > target) { right--; } else { left++; } } return new int[]{left+1, left + 2}; } }
class Solution { public int[] twoSum(int[] numbers, int target) { int middle = target / 2; int left = 0; int right = 0; for (int i = 0; i < numbers.length-1; i++) { if (numbers[i]==middle&&numbers[i+1]==middle){ return new int[]{i+1 , i + 2}; } } for (int i = 0; i < numbers.length; i++) { if (numbers[i]<=target / 2.0&&numbers[i+1]>=target / 2.0){ left = i; right = i+1; break; } } int sum = numbers[left]+numbers[right]; while (sum!=target){ if (sum<target){ right++; }else { left--; } sum = numbers[left]+numbers[right]; } int[] newNum = {left+1,right+1}; return newNum; } }
题目:给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
class Solution { public int minSubArrayLen(int target, int[] nums) { int n = nums.length; if (n == 0) { return 0; } int ans = Integer.MAX_VALUE; int start = 0, end = 0; int sum = 0; while (end < n) { sum += nums[end]; while (sum >= target) { ans = Math.min(ans, end - start + 1); sum -= nums[start]; start++; } end++; } return ans == Integer.MAX_VALUE ? 0 : ans; } }
题目:给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。请不要使用除法,且在 O(n) 时间复杂度内完成此题。
class Solution { public int[] productExceptSelf(int[] nums) { int n = nums.length; int[] left = new int[n]; int[] right = new int[n]; int temp = 1; left[0] = 1; for (int i = 1; i < n; i++) { temp *= nums[i - 1]; left[i] = temp; } temp = 1; right[n-1] = 1; for (int i = n - 2; i >= 0; i--) { temp *= nums[i + 1]; right[i] = temp; } int result[] = new int[n]; for (int i = 0; i < n; i++) { result[i] = left[i] * right[i]; } return result; } }
题目:给你一个整数数组
nums
,有一个大小为k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的k
个数字。滑动窗口每次只向右移动一位。返回 滑动窗口中的最大值 。
思路1:单调队列模板题,求滑动窗口的最值。
class Solution { public int[] maxSlidingWindow(int[] nums, int k) { if(nums == null || nums.length == 0) { return new int[0]; } int[] res = new int[nums.length - k + 1]; Deque<Integer> queue = new ArrayDeque<>(); for(int i = 0, j = 0; i < nums.length; i++) { if(!queue.isEmpty() && i - queue.peek() >= k) { queue.poll(); } while(!queue.isEmpty() && nums[i] > nums[queue.peekLast()]) { queue.pollLast(); } queue.offer(i); if(i >= k - 1) { res[j++] = nums[queue.peek()]; } } return res; } }思路2:暴力加速
class Solution { public int[] maxSlidingWindow(int[] nums, int k) { // 加速原理:每次滑动窗口向右移动时,判断 // a. 新加入的值 是否比上一个窗口最大值大,若是,则直接返回 新加入的值 // b. 待移除的值 是否比上一个窗口最大值小,若是,则返回 上一窗口最大值 if(k==0)return new int[0]; int ans[] = new int[nums.length-k+1]; // 记录每一窗口的最大值 for(int i=0;i+k-1<nums.length;i++){ if(i>0 && nums[i+k-1]>ans[i-1])ans[i] = nums[i+k-1]; // 新值比上一窗口最大值大,返回 新值 else if(i>0 && nums[i-1]<ans[i-1])ans[i] = ans[i-1]; // 旧值比上一窗口最大值小,返回 上一窗口最大值 else{ // 遍历滑动窗口,找到最大值 int max = Integer.MAX_VALUE+1; for(int j=i;j<i+k;j++){ max = Math.max(max,nums[j]); ans[i] = max; } } } return ans; } }
题目:给你一个整数数组
nums
和一个整数target
。向数组中的每个整数前添加'+'
或'-'
,然后串联起所有整数,可以构造一个 表达式 :
- 例如,
nums = [2, 1]
,可以在2
之前添加'+'
,在1
之前添加'-'
,然后串联起来得到表达式"+2-1"
。返回可以通过上述方法构造的、运算结果等于
target
的不同 表达式 的数目。
class Solution { public int findTargetSumWays(int[] nums, int t) { int n = nums.length; int sum = Arrays.stream(nums).sum(); if (sum < Math.abs(t)) return 0; int[][] dp = new int[n][sum * 2 + 1]; dp[0][nums[0] + sum] = 1; dp[0][sum - nums[0]] += 1; for (int i = 1; i < n; i++) { int num = nums[i]; for (int j = -sum; j <= sum; j++) { int res = 0; if (j + sum - num >= 0) res += dp[i - 1][j + sum - num]; if (j + sum + num <= 2 * sum) res += dp[i - 1][j + sum + num]; dp[i][j + sum] = res; } } return dp[n - 1][t + sum]; } }
题目:给你一个整数数组
nums
和一个整数k
,请你统计并返回 该数组中和为k
的连续子数组的个数 。
class Solution { public int subarraySum(int[] nums, int k) { if (nums == null || nums.length == 0) { return 0; } int N = nums.length; int ans = 0; for (int i = 0; i < N; i++) { int sum = 0; for (int j = i; j < N; j++) { sum += nums[j]; if (sum == k) { ans++; } } } return ans; } }
题目:给定一个非负整数
c
,你要判断是否存在两个整数a
和b
,使得a2 + b2 = c
。
class Solution { public boolean judgeSquareSum(int c) { if (c == 1 || c == 2) { return true; } int left = 0; int right = (int) Math.sqrt(c); while (left <= right) { int left2 = left * left; int right2 = right * right; int left3 = c-right2; if (left2 < left3) { left++; } else if (left2 > left3) { right--; } else { return true; } } return false; } }
题目:给你一个整数数组
nums
和一个整数k
,请你返回子数组内所有元素的乘积严格小于k
的连续子数组的数目。
class Solution { public int numSubarrayProductLessThanK(int[] nums, int k) { // 滑动窗口:寻找以每个 right 指针为右边界的有效连续子树组的个数 int length = nums.length; int product = 1; int cnt = 0; int left = 0, right = 0; while (right < length) { product *= nums[right++]; while (left < right && product >= k) { product /= nums[left++]; } cnt += (right - left); } return cnt; } }
题目:给你一个整数数组 nums,和一个整数 k 。对于每个下标 i(0 <= i < nums.length),将 nums[i] 变成 nums[i] + k 或 nums[i] - k 。nums 的 分数 是 nums 中最大元素和最小元素的差值。在更改每个下标对应的值之后,返回 nums 的最小 分数 。
class Solution { public int smallestRangeII(int[] A, int K) { if(A==null||A.length==0){ return 0; } Arrays.sort(A);//排序 int ans=A[A.length-1]-A[0]; int min,max; for(int i=1;i<A.length;i++){//每次划分将A[i]前面的数全部+K,A[i]后面的数全部-K min=Math.min(A[0]+K,A[i]-K);//最小值可能是第一个值+K,也可能是划分后右边第一个数-K max=Math.max(A[A.length-1]-K,A[i-1]+K);//最大值同理 ans=Math.min(ans,max-min); } return ans; } }
题目:给你一个按 非递减顺序 排序的整数数组
nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
class Solution { public int[] sortedSquares(int[] nums) { int left = 0; int right = nums.length-1; int newNums[] = new int[nums.length]; int index = right; while (left < right) { boolean flag = nums[left] * nums[left] >= nums[right] * nums[right]; if (flag) { newNums[index] = nums[left] * nums[left]; left += 1; } else { newNums[index] = nums[right] * nums[right]; right--; } index--; } newNums[index] = nums[left] * nums[left]; return newNums; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。