这篇文章是leetcode
刷题系列的第1
部分——数组。这里把有代表性的题目发出来,共计82
道。主要涉及滑动窗口、哈希表、堆、二分搜索、扫描线、区间相关、拓扑排序、树状数组等算法。
leetcode
刷题系列其它文章组织如下:
1
. 数组
2
. 链表
3
. 字符串
4
. 二叉树
5
. 队列和栈
6
. 动态规划
7
. 数据结构设计
8
. 刷题小知识点
给定一个有序整数数组 和一个目标数,在数组中找到总和等于目标数的两个元素,返回它们的索引。
Example:
1 2 3 Input: numbers = [2,7,11,15], target = 9 Output: [1,2] Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 vector <int > twoSum (vector <int > nums, int target) { int n = nums.size(); int left = 0 ; int right = n - 1 ; while (left < right) { int sum = nums[left] + nums[right]; if (sum == target) { return {left + 1 , right + 1 }; } else if (sum < target) { left++; } else { right--; } } return {}; }
给定一个无序整数数组 和一个目标数,在数组中找到总和等于目标数的两个元素,返回它们的索引。
Example:
1 2 Input: nums = [3,2,4], target = 6 Output: [1,2]
1 2 3 4 5 6 7 8 9 10 11 12 13 vector <int > twoSum (vector <int > nums, int target) { unordered_map <int , int > mapping; for (int i = 0 ; i < nums.size(); i++) { if (mapping.count(target - nums[i])) { return {mapping[target - nums[i]], i}; } else { mapping[nums[i]] = i; } } return {}; }
给定一个整数数组和一个目标数,返回数组中其总和等于目标数的连续子数组的个数 。
Example:
1 2 Input: nums = [1,1,1], k = 2 Output: 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int subarraySum (vector <int >& nums, int k) { int n = nums.size(); int res = 0 ; for (int i = 0 ; i < n; i++) { int sum = 0 ; for (int j = i; j < n; j++) { sum += nums[j]; if (sum == k) { res++; } } } return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int subarraySum (vector <int >& nums, int k) { int n = nums.size(); unordered_map <int , int > mapping; int res = 0 , sum = 0 ; mapping[0 ] = 1 ; for (int i = 0 ; i < n; i++) { sum += nums[i]; if (mapping.count(sum - k)) { res += mapping[sum - k]; } mapping[sum]++; } return res; }
给定一个整数数组,请计算该数组的枢轴索引。枢轴索引使得该索引左侧的所有数字的总和等于在该索引右侧的所有数字的总和。
如果索引在数组的左边缘,则左总和为0
,因为左侧没有元素,这也适用于数组的右边缘。如果存在多个枢轴索引,返回最左边的。 如果不存在这样的索引,则返回-1
。
Example 1:
1 2 3 4 5 6 Input: nums = [1,7,3,6,5,6] Output: 3 Explanation: The pivot index is 3. Left sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 Right sum = nums[4] + nums[5] = 5 + 6 = 11
Example 2:
1 2 3 4 Input: nums = [1,2,3] Output: -1 Explanation: There is no index that satisfies the conditions in the problem statement.
Example 3:
1 2 3 4 5 6 Input: nums = [2,1,-1] Output: 0 Explanation: The pivot index is 0. Left sum = 0 (no elements to the left of index 0) Right sum = nums[1] + nums[2] = 1 + -1 = 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int pivotIndex (vector <int >& nums) { int n = nums.size(); vector <int > prefix (n + 1 ) ; for (int i = 0 ; i < n; i++) { prefix[i + 1 ] = prefix[i] + nums[i]; } for (int i = 0 ; i < n; i++) { if ((prefix[i] - prefix[0 ]) == (prefix[n] - prefix[i + 1 ])) { return i; } } return -1 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 int pivotIndex (vector <int >& nums) { int n = nums.size(); int sum = accumulate(nums.begin(), nums.end(), 0 ); int leftSum = 0 ; for (int i = 0 ; i < n; i++) { if (sum - leftSum - nums[i] == leftSum) { return i; } leftSum += nums[i]; } return -1 ; }
给定一个非负整数数组和目标整数k
,编写一个函数以检查该数组是否具有大小至少为2
的连续子数组,该子数组的总和为k
的倍数。
Example 1:
1 2 3 >Input: [23, 2, 4, 6, 7], k = 6 >Output: True >Explanation: Because [2, 4] is a continuous subarray of size 2 and sums up to 6.
Example 2:
1 2 3 >Input: [23, 2, 6, 4, 7], k = 6 >Output: True >Explanation: Because [23, 2, 6, 4, 7] is an continuous subarray of size 5 and sums up to 42.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 bool checkSubarraySum (vector <int >& nums, int k) { int n = nums.size(); unordered_map <int , int > mapping; int sum = 0 ; mapping[0 ] = -1 ; for (int i = 0 ; i < n; i++) { sum += nums[i]; int mod = sum % k; if (mapping.count(mod)) { if (i - mapping[mod] > 1 ) { return true ; } } else { mapping[mod] = i; } } return false ; }
给定固定长度的整数数组arr
,请复制每次出现的零,将其余元素向右移动。请注意,不会写入超出原始数组长度的元素。
对输入数组进行就地修改,不要从函数中返回任何内容。
Example 1:
1 2 3 Input: [1,0,2,3,0,4,5,0] Output: null Explanation: After calling your function, the input array is modified to: [1,0,0,2,3,0,0,4]
Example 2:
1 2 3 Input: [1,2,3] Output: null Explanation: After calling your function, the input array is modified to: [1,2,3]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 void duplicateZeros (vector <int > &arr) { int n = arr.size(); int zerosCnt = count(arr.begin(), arr.end(), 0 ); if (zerosCnt == 0 ) { return ; } for (int i = n - 1 ; i >= 0 ; i--) { if (arr[i] != 0 ) { int newPos = i + zerosCnt; if (newPos < n) { arr[newPos] = arr[i]; } arr[i] = 0 ; } else { zerosCnt--; if (zerosCnt == 0 ) { break ; } } } }
给定一个整数数组arr
,当且仅当它是有效的山峰数组时,才返回true
。当且仅当满足以下条件时,arr
是一个山峰数组:
arr.size() >= 3
There exists some i
with 0 < i < arr.size() - 1
such that:
arr[0] < arr[1] < ... < arr[i - 1] < arr[i]
arr[i] > arr[i + 1] > ... > arr[arr.size() - 1]
Example 1:
1 2 Input: arr = [2,1] Output: false
Example 2:
1 2 Input: arr = [3,5,5] Output: false
Example 3:
1 2 Input: arr = [0,3,2,1] Output: true
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 bool validMountainArray (vector <int >& arr) { int n = arr.size(); int i = 0 ; while (i + 1 < n && arr[i] < arr[i + 1 ]) { i++; } if (i == 0 || i == n - 1 ) { return false ; } while (i + 1 < n && arr[i] > arr[i + 1 ]) { i++; } return i == n - 1 ; }
给定一个整数数组,其中1 ≤ a[i] ≤ n (n = 数组大小)
,某些元素出现两次,而另一些元素出现一次。查找[1,n]
包含的所有未出现在此数组中的元素。
Example:
1 2 3 4 5 Input: [4,3,2,7,8,2,3,1] Output: [5,6]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 vector <int > findDisappearedNumbers (vector <int >& nums) { int n = nums.size(); for (int i = 0 ; i < n; i++) { int index = abs (nums[i]) - 1 ; if (nums[index] > 0 ) { nums[index] = -nums[index]; } } vector <int > res; for (int i = 0 ; i < n; i++) { if (nums[i] > 0 ) { res.push_back(i + 1 ); } } return res; }
给定一个整数数组,即1 ≤ a[i] ≤ n (n = 数组大小)
,其中有些元素出现两次 而其他元素出现一次 。找到所有出现两次 的元素。
Example:
1 2 3 4 5 Input: [4,3,2,7,8,2,3,1] Output: [2,3]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 vector <int > findDuplicates (vector <int >& nums) { vector <int > res; for (int i = 0 ; i < nums.size(); i++) { int index = abs (nums[i]) - 1 ; if (nums[index] < 0 ) { res.push_back(index + 1 ); } else { nums[index] = -nums[index]; } } return res; }
给你一个下标从0
开始的正整数数组candiesCount
,其中candiesCount[i]
表示你拥有的第i
类糖果的数目。同时给你一个二维数组queries
,其中queries[i] = [favoriteTypei, favoriteDayi, dailyCapi]
。
你按照如下规则进行一场游戏:
你从第0
天开始吃糖果。
你在吃完所有第i - 1
类糖果之前,不能吃任何一颗第i
类糖果。
在吃完所有糖果之前,你必须每天至少吃一颗糖果。
请你构建一个布尔型数组answer
,满足answer.length == queries.length
。answer[i]
为true
的条件是:在每天吃不超过dailyCap_i
颗糖果的前提下,你可以在第favoriteDay_i
天吃到第favoriteType_i
类糖果;否则answer[i]
为false
。注意,只要满足上面3
条规则中的第二条规则,你就可以在同一天吃不同类型的糖果。
请你返回得到的数组answer
。
示例 :
1 2 3 4 5 6 输入:candiesCount = [7,4,5,3,8], queries = [[0,2,2],[4,2,4],[2,13,1000000000]] 输出:[true,false,true] 提示: 1. 在第 0 天吃 2 颗糖果(类型 0),第 1 天吃 2 颗糖果(类型 0),第 2 天你可以吃到类型 0 的糖果 2. 每天你最多吃 4 颗糖果。即使第 0 天吃 4 颗糖果(类型 0),第 1 天吃 4 颗糖果(类型 0 和类型 1),你也没办法在第 2 天吃到类型 4 的糖果。换言之,你没法在每天吃 4 颗糖果的限制下在第 2 天吃到第 4 类糖果 3. 如果你每天吃 1 颗糖果,你可以在第 13 天吃到类型 2 的糖果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 vector <bool > canEat (vector <int > candiesCount, vector <vector <int >> queries) { int n = candiesCount.size(); vector <long > prefixSum (n + 1 ) ; for (int i = 1 ; i <= n; i++) prefixSum[i] = prefixSum[i - 1 ] + candiesCount[i - 1 ]; vector <bool > res; res.reserve(queries.size()); for (auto &query : queries) { long x1 = query[1 ] + 1 ; long y1 = long ((query[1 ] + 1 )) * query[2 ]; long x2 = prefixSum[query[0 ]] + 1 ; long y2 = prefixSum[query[0 ] + 1 ]; res.push_back(x1 <= y2 && x2 <= y1); } return res; }
给你输入一个正整数N
,代表左闭右开区间[0,N)
,再给你输入一个数组blacklist
,其中包含一些「黑名单数字」,且blacklist
中的数字都是区间[0,N)
中的数字。
编写一个函数以随机返回[0,N)
中的一个整数,该整数不在blacklist
中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class Solution {private : int actual; unordered_map <int , int > mapping; public : Solution(int N, vector <int >& blacklist) { for (int val : blacklist) { mapping[val] = 0 ; } actual = N - blacklist.size(); for (int val : blacklist) { if (val < actual) { N--; while (mapping.count(N)) { N--; } mapping[val] = N; } } } int pick () { int i = rand() % actual; if (mapping.count(i) > 0 ) { return mapping[i]; } return i; } };
给定一个正整数数组w
,其中w[i]
描述第i
个索引的权重。
我们需要调用函数pickIndex()
,该函数随机返回范围为[0,w.size())
的整数。 pickIndex()
应该返回与其在w
数组中的权重成比例的数。 例如,对于w = [1,3]
,选择索引0
的概率为1 / (1 + 3) = 0.25
,而选择索引1
的概率为3 / (1 + 3) = 0.75
。或者说,选择索引i
的概率为w[i] / sum(w)
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Solution {private : vector <int > prefixSum; public : Solution(vector <int >& w) : prefixSum(w.size() + 1 ) { for (int i = 0 ; i < w.size(); i++) { prefixSum[i + 1 ] = prefixSum[i] + w[i]; } } int pickIndex () { int target = rand() % prefixSum.back(); int lo = 0 , hi = prefixSum.size(); while (lo < hi) { int mi = (hi + lo) / 2 ; if (prefixSum[mi] <= target) { lo = mi + 1 ; } else { hi = mi; } } return lo - 1 ; } };
给你n
个非负整数a1, a2, ..., an
,每个数代表坐标中的一个点(i, ai)
。在坐标内画n
条垂直线,垂直线i
的两个端点分别为(i, ai)
和(i, 0)
。找出其中的两条线,使得它们与x
轴共同构成的容器可以容纳最多的水。
返回容纳的水量。
Example:
1 2 3 Input: height = [1,8,6,2,5,4,8,3,7] Output: 49 Explanation: The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int maxArea (vector <int >& height) { int n = height.size(); int left = 0 , right = n - 1 ; int res = 0 ; while (left < right) { if (height[left] <= height[right]) { res = max(res, (right - left) * height[left]); left++; } else { res = max(res, (right - left) * height[right]); right--; } } return res; }
给定n
个表示海拔图的非负整数,其中每个条的宽度为1
,计算下雨后它可以捕集多少水。
Example:
1 2 3 Input: height = [0,1,0,2,1,0,1,3,2,1,2,1] Output: 6 Explanation: The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 int trap (vector <int >& height) { if (height.empty()) { return 0 ; } int n = height.size(); vector <int > left_max (n) ; vector <int > right_max (n) ; left_max.front() = height.front(); right_max.back() = height.back(); for (int i = 1 ; i < n; i++) { left_max[i] = max(height[i], left_max[i - 1 ]); } for (int i = n - 2 ; i >= 0 ; i--) { right_max[i] = max(height[i], right_max[i + 1 ]); } int res = 0 ; for (int i = 0 ; i < n; i++) { res += min(left_max[i], right_max[i]) - height[i]; } return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 int trap (vector <int >& height) { int n = height.size(); int left = 0 , right = n - 1 ; int left_max = 0 , right_max = 0 ; int res = 0 ; while (left < right) { left_max = max(left_max, height[left]); right_max = max(right_max, height[right]); if (left_max < right_max) { res += left_max - height[left]; left++; } else { res += right_max - height[right]; right--; } } return res; }
n
名士兵站成一排。每个士兵都有一个独一无二的评分 rating
。每3
个士兵可以组成一个作战单位,分组规则如下:
从队伍中选出下标分别为i、j、k
的3
名士兵,他们的评分分别为rating[i]、rating[j]、rating[k]
;
作战单位需满足:rating[i] < rating[j] < rating[k]
或者rating[i] > rating[j] > rating[k]
,其中0 <= i < j < k < n
。
你返回按上述条件可以组建的作战单位数量。每个士兵都可以是多个作战单位的一部分。
Example 1 :
1 2 3 Input: rating = [2,5,3,4,1] Output: 3 Explanation: We can form three teams given the conditions. (2,3,4), (5,4,1), (5,3,1).
Example 2 :
1 2 3 Input: rating = [2,1,3] Output: 0 Explanation: We can't form any team given the conditions.
Example 3 :
1 2 Input: rating = [1,2,3,4] Output: 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int numTeams (vector <int >& rating) { int n = rating.size(); vector <int > right_max (n) ; vector <int > right_min (n) ; for (int i = 0 ; i < n; i++) { for (int j = i + 1 ; j < n; j++) { if (rating[i] < rating[j]) { right_max[i]++; } else { right_min[i]++; } } } int res = 0 ; for (int i = 0 ; i < n; i++) { for (int j = i + 1 ; j < n; j++) { if (rating[i] < rating[j]) { res += right_max[j]; } else { res += right_min[j]; } } } return res; }
中值是有序整数列表中的中间值。 如果列表的大小是偶数,则没有中间值,此时,中位数是两个中间值的平均值。
给定一个数组num
,存在一个大小为k
的滑动窗口,该窗口从数组的最左边移到最右边。 你只能在窗口中看到k
个数字。 每次滑动窗口向右移动一个位置。 你的工作是输出原始数组中每个窗口的中值数组。
For example, Given nums = [1,3,-1,-3,5,3,6,7]
, and k = 3.
1 2 3 4 5 6 7 8 Window position Median --------------- ------ [1 3 -1] -3 5 3 6 7 1 1 [3 -1 -3] 5 3 6 7 -1 1 3 [-1 -3 5] 3 6 7 -1 1 3 -1 [-3 5 3] 6 7 3 1 3 -1 -3 [5 3 6] 7 5 1 3 -1 -3 5 [3 6 7] 6
Therefore, return the median sliding window as[1,-1,-1,3,5,6]
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 vector <double > medianSlidingWindow (vector <int >& nums, int k) { int n = nums.size(); vector <double > median; multiset <int > window (nums.begin(), next(nums.begin(), k)) ; auto mid = next(window.begin(), k / 2 ); for (int i = k; ; i++) { if (k & 1 ) { median.push_back(*mid); } else { median.push_back((double (*prev(mid)) + double (*mid)) * 0.5 ); } if (i == n) { break ; } window.insert(nums[i]); if (nums[i] < *mid) { mid--; } if (nums[i - k] <= *mid) { mid++; } window.erase(window.lower_bound(nums[i - k])); } return median; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 vector <double > medianSlidingWindow (vector <int >& nums, int k) { if (k & 1 ) { return medianSlidingWindowForOdd(nums, k); } return medianSlidingWindowForEven(nums, k); } vector <double > medianSlidingWindowForOdd (vector <int >& nums, int k) { vector <double > median; multiset <int > window (nums.begin(), next(nums.begin(), k)) ; auto mid = next(window.begin(), k / 2 ); for (int i = k; ; i++) { median.push_back(*mid); if (i == nums.size()) { break ; } window.insert(nums[i]); if (nums[i] >= *mid) { ++mid; } if (nums[i - k] < *mid) { window.erase(window.find(nums[i - k])); } else if (nums[i - k] > *mid) { window.erase(window.find(nums[i - k])); --mid; } else { mid = window.erase(mid); --mid; } } return median; } vector <double > medianSlidingWindowForEven (vector <int >& nums, int k) { vector <double > median; multiset <int > window (nums.begin(), next(nums.begin(), k)) ; auto mid = next(window.begin(), k / 2 ); for (int i = k; ; i++) { median.push_back((double (*prev(mid)) + double (*mid)) * 0.5 ); if (i == nums.size()) { break ; } window.insert(nums[i]); if (nums[i] < *mid) { --mid; } if (nums[i - k] < *mid) { window.erase(window.find(nums[i - k])); ++mid; } else if (nums[i - k] > *mid) { window.erase(window.find(nums[i - k])); } else { mid = window.erase(mid); } } return median; }
给你一个整数数组num
,有一个大小为k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的k
个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
Example:
1 2 3 4 5 6 7 8 9 10 11 Input: nums = [1,3,-1,-3,5,3,6,7], k = 3 Output: [3,3,5,5,6,7] Explanation: Window position Max --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class MonoQ {private : deque <int > monoQ; public : void push (int val) { while (!monoQ.empty() && monoQ.back() < val) { monoQ.pop_back(); } monoQ.push_back(val); } void pop (int val) { if (monoQ.front() == val) { monoQ.pop_front(); } } int maxVal () { return monoQ.front(); } }; vector <int > maxSlidingWindow (vector <int >& nums, int k) { int n = nums.size(); vector <int > res; MonoQ monoQ; for (int i = 0 ; i < n; i++) { monoQ.push(nums[i]); if (i >= k - 1 ) { res.push_back(monoQ.maxVal()); monoQ.pop(nums[i - k + 1 ]); } } return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 vector <int > maxSlidingWindow (vector <int >& nums, int k) { int n = nums.size(); vector <int > res; deque <int > monoQ; for (int i = 0 ; i < n; i++) { while (!monoQ.empty() && monoQ.back() < nums[i]) { monoQ.pop_back(); } monoQ.push_back(nums[i]); if (i >= k - 1 ) { res.push_back(monoQ.front()); if (monoQ.front() == nums[i - k + 1 ]) { monoQ.pop_front(); } } } return res; }
给你一个二维数组tasks
,用于表示n
项从0
到n - 1
编号的任务。其中tasks[i] = [enqueueTimei, processingTimei]
意味着第i
项任务将会于enqueueTimei
时进入任务队列,需要processingTimei
的时长完成执行。
现有一个单线程CPU
,同一时间只能执行最多一项任务,该CPU
将会按照下述方式运行:
如果CPU
空闲,且任务队列中没有需要执行的任务,则CPU
保持空闲状态。
如果CPU
空闲,但任务队列中有需要执行的任务,则CPU
将会选择执行时间最短的任务开始执行。如果多个任务具有同样的最短执行时间,则选择下标最小的任务开始执行。
一旦某项任务开始执行,CPU
在执行完整个任务前都不会停止。
CPU
可以在完成一项任务后,立即开始执行一项新任务。
返回CPU
处理任务的顺序。
Example 1:
1 2 3 4 5 6 7 8 9 10 11 12 >Input: tasks = [[1,2],[2,4],[3,2],[4,1]] >Output: [0,2,3,1] >Explanation: The events go as follows: >- At time = 1, task 0 is available to process. Available tasks = {0}. >- Also at time = 1, the idle CPU starts processing task 0. Available tasks = {}. >- At time = 2, task 1 is available to process. Available tasks = {1}. >- At time = 3, task 2 is available to process. Available tasks = {1, 2}. >- Also at time = 3, the CPU finishes task 0 and starts processing task 2 as it is the shortest. Available tasks = {1}. >- At time = 4, task 3 is available to process. Available tasks = {1, 3}. >- At time = 5, the CPU finishes task 2 and starts processing task 3 as it is the shortest. Available tasks = {1}. >- At time = 6, the CPU finishes task 3 and starts processing task 1. Available tasks = {}. >- At time = 10, the CPU finishes task 1 and becomes idle.
Example 2:
1 2 3 4 5 6 7 8 9 10 >Input: tasks = [[7,10],[7,12],[7,5],[7,4],[7,2]] >Output: [4,3,2,0,1] >Explanation: The events go as follows: >- At time = 7, all the tasks become available. Available tasks = {0,1,2,3,4}. >- Also at time = 7, the idle CPU starts processing task 4. Available tasks = {0,1,2,3}. >- At time = 9, the CPU finishes task 4 and starts processing task 3. Available tasks = {0,1,2}. >- At time = 13, the CPU finishes task 3 and starts processing task 2. Available tasks = {0,1}. >- At time = 18, the CPU finishes task 2 and starts processing task 0. Available tasks = {1}. >- At time = 28, the CPU finishes task 0 and starts processing task 1. Available tasks = {}. >- At time = 40, the CPU finishes task 1 and becomes idle.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 using Pair = pair<int , int >;vector <int > getOrder (vector <vector <int >>& tasks) { int taskCount = tasks.size(); for (int taskId = 0 ; taskId < taskCount; taskId++) { tasks[taskId].push_back(taskId); } sort(tasks.begin(), tasks.end()); vector <int > res; priority_queue<Pair, vector <Pair>, greater<Pair>> tasksQueue; int taskId = 0 ; long timeStamp = 0 ; while (taskId < taskCount || !tasksQueue.empty()) { if (tasksQueue.empty()) { timeStamp = max(timeStamp, (long )tasks[taskId][0 ]); } while (taskId < taskCount && tasks[taskId][0 ] <= timeStamp) { tasksQueue.push({tasks[taskId][1 ], tasks[taskId][2 ]}); taskId++; } auto [duration, id] = tasksQueue.top(); tasksQueue.pop(); timeStamp += duration; res.push_back(id); } return res; }
给你一个整数数组nums
,请你将该数组升序排列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 void sortArray (vector <int > &nums) { auto down = [&](int hole, int n) { int holeVal = nums[hole]; for (int lc = 2 * hole + 1 ; lc < n; lc = 2 * hole + 1 ) { if (lc + 1 < n && nums[lc] <= nums[lc + 1 ]) { lc++; } if (nums[lc] <= holeVal) { break ; } nums[hole] = nums[lc]; hole = lc; } nums[hole] = holeVal; }; int n = nums.size(); int lastInternal = (n - 1 - 1 ) / 2 ; while (lastInternal >= 0 ) { down(lastInternal--, n); } for (int i = n - 1 ; i > 0 ; i--) { swap(nums[i], nums[0 ]); down(0 , i); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 vector <int > sortArray (vector <int > &nums) { int n = nums.size(); mergeSort(nums, 0 , n - 1 ); return nums; } void mergeSort (vector <int > &nums, int lo, int hi) { if (hi - lo < 1 ) { return ; } int mi = lo + (hi - lo) / 2 ; mergeSort(nums, lo, mi); mergeSort(nums, mi + 1 , hi); merge(nums, lo, mi, hi); } void merge (vector <int > &nums, int lo, int mi, int hi) { vector <int > helper (next(nums.begin(), mi + 1 ), next(nums.begin(), hi + 1 )) ; int i = mi; int j = hi - mi - 1 ; int k = hi; while (i >= lo && j >= 0 ) { if (nums[i] > helper[j]) { nums[k--] = nums[i--]; } else { nums[k--] = helper[j--]; } } while (j >= 0 ) { nums[k--] = helper[j--]; } } vector <int > sortArray (vector <int >& nums) { int sz = nums.size(); for (int step = 1 ; step <= sz; step *= 2 ) { for (int lo = 0 ; lo < sz; lo += 2 * step) { merge(nums, lo, min(lo + step - 1 , sz - 1 ), min(lo + 2 * step - 1 , sz - 1 )); } } return nums; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 vector <int > sortArray (vector <int > &nums) { int n = nums.size(); quickSort(nums, 0 , n - 1 ); return nums; } void quickSort (vector <int > &nums, int lo, int hi) { if (lo >= hi) { return ; } auto shuffle = [&](int lo, int hi) { for (int i = lo; i <= hi; i++) { int j = rand() % (hi - i + 1 ) + i; swap(nums[i], nums[j]); } }; auto partition = [&](int lo, int hi) { shuffle(lo, hi); int i = lo, j = lo; while (++j <= hi) { if (nums[j] <= nums[lo]) { swap(nums[++i], nums[j]); } } swap(nums[lo], nums[i]); return i; }; int pivot = partition(lo, hi); quickSort(nums, lo, pivot - 1 ); quickSort(nums, pivot + 1 , hi); }
给定一个以升序排列的整数nums
数组,请找到给定目标值的开始和结束位置。如果在数组中未找到目标,则返回[-1,-1]
。
Example 1:
1 2 Input: nums = [5,7,7,8,8,10], target = 8 Output: [3,4]
Example 2:
1 2 Input: nums = [5,7,7,8,8,10], target = 6 Output: [-1,-1]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 vector <int > searchRange (vector <int >& nums, int target) { int left = right_bound(nums, target - 1 ); int right = right_bound(nums, target); if (left < 0 || left >= nums.size() || nums[left] != target) { return {-1 , -1 }; } return {left, right - 1 }; } int right_bound (vector <int >& nums, int target) { int lo = 0 , hi = nums.size(); while (lo < hi) { int mi = lo + (hi - lo >> 1 ); if (target >= nums[mi]) { lo = mi + 1 ; } else { hi = mi; } } return lo; }
编写一个高效的算法来搜索m x n
矩阵matrix
中的一个目标值target
。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
Example 1:
1 2 Input: matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20 Output: false
Example 2:
1 2 Input: matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5 Output: true
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 bool searchMatrix (vector <vector <int >>& matrix, int target) { int n = matrix.size(); if (n == 0 ) { return false ; } int r = 0 , c = matrix[0 ].size() - 1 ; while (r < n && c >= 0 ) { if (target < matrix[r][c]) { c--; } else if (target > matrix[r][c]) { r++; } else { return true ; } } return false ; }
峰值元素是指其值严格大于左右相邻值的元素。给你一个输入数组nums
,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回任何一个峰值 所在位置即可。
你可以假设nums[-1] = nums[n] = -∞
。
Example 1:
1 2 3 Input: nums = [1,2,3,1] Output: 2 Explanation: 3 is a peak element and your function should return the index number 2.
Example 2:
1 2 3 Input: nums = [1,2,1,3,5,6,4] Output: 5 Explanation: Your function can return either index number 1 where the peak element is 2, or index number 5 where the peak element is 6.
1 2 3 4 5 6 7 8 9 10 11 12 13 int findPeakElement (vector <int >& nums) { int lo = 0 , hi = nums.size() - 1 ; while (lo < hi) { int mi = lo + (hi - lo >> 1 ); if (nums[mi] > nums[mi + 1 ]) hi = mi; else lo = mi + 1 ; } return lo; }
给定一个排序好的数组arr
,两个整数k
和x
,从数组中找到最靠近x
(两数之差最小)的k
个数。返回的结果必须要是按升序排好的。
整数a
比整数b
更接近x
需要满足:
|a - x| < |b - x|
或者
|a - x| == |b - x|
且a < b
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 vector <int > findClosestElements (vector <int >& arr, int k, int x) { vector <int > res (arr) ; sort(res.begin(), res.end(), [x](int a, int b) { return abs (a - x) == abs (b - x) ? a < b : abs (a - x) < abs (b - x); }); res.resize(k); sort(res.begin(), res.end()); return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 vector <int > findClosestElements (vector <int > &arr, int k, int x) { vector <int > res; int lo = 0 , hi = arr.size(); while (lo < hi) { int mi = lo + (hi - lo >> 1 ); if (x <= arr[mi]) { hi = mi; } else { lo = mi + 1 ; } } if (lo == 0 ) { copy(arr.begin(), arr.end(), back_inserter(res)); } else if (lo == arr.size()) { copy(prev(arr.end(), k), arr.end(), back_inserter(res)); } else { int left = max(lo - k, 0 ); int right = min(lo + k, int (arr.size()) - 1 ); while (right - left > k - 1 ) { if (abs (arr[left] - x) <= abs (arr[right] - x)) { right--; } else { left++; } } copy(next(arr.begin(), left), next(arr.begin(), left + k), back_inserter(res)); } return res; }
给定一个整数数组,返回所有数对之间的第k
个最小距离 。一对(A, B)
的距离被定义为A
和B
之间的绝对差值。
Note:
2 <= len(nums) <= 10000
.
0 <= nums[i] < 1000000
.
1 <= k <= len(nums) * (len(nums) - 1) / 2
.
Example:
1 2 3 4 5 6 7 8 9 10 Input: nums = [1,3,1] k = 1 Output: 0 Explanation: Here are all the pairs: (1,3) -> 2 (1,1) -> 0 (3,1) -> 2 Then the 1st smallest distance pair is (1,1), and its distance is 0.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 int smallestDistancePair (vector <int >& nums, int k) { vector <int > distances; for (int i = 0 ; i < nums.size(); i++) for (int j = i + 1 ; j < nums.size(); j++) distances.push_back(abs (nums[i] - nums[j])); int lo = 0 , hi = distances.size() - 1 ; while (lo <= hi) { int pivot = partition(distances, lo, hi); if (pivot == k - 1 ) return distances[pivot]; else if (pivot < k - 1 ) lo = pivot + 1 ; else hi = pivot - 1 ; } return 0 ; } int partition (vector <int >& nums, int lo, int hi) { int i = lo, j = lo; while (++j <= hi) if (nums[j] < nums[lo]) swap(nums[++i], nums[j]); swap(nums[lo], nums[i]); return i; } int smallestDistancePair (vector <int >& nums, int k) { multiset <int > setting; for (int i = 0 ; i < nums.size(); i++) for (int j = i + 1 ; j < nums.size(); j++) setting.insert(abs (nums[i] - nums[j])); auto it = next(setting.begin(), k - 1 ); return *it; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 int smallestDistancePair (vector <int >& nums, int k) { sort(nums.begin(), nums.end()); int lo = 0 ; int hi = nums.back() - nums[0 ]; while (lo < hi) { int mi = lo + (hi - lo) / 2 ; int count = 0 , left = 0 , right = 1 ; while (right < nums.size()) { while (nums[right] - nums[left] > mi) left++; count += right - left; right++; } if (k <= count) hi = mi; else lo = mi + 1 ; } return lo; }
给定两个以升序排列的整形数组nums1
和nums2
,以及一个整数k
。
定义一对值(u,v)
,其中第一个元素来自nums1
,第二个元素来自nums2
。
找到和最小的k
对数字(u1,v1),(u2,v2)...(uk,vk)
。
Constraints:
1 <= nums1.length, nums2.length <= 104
-109 <= nums1[i], nums2[i] <= 109
nums1
and nums2
both are sorted in ascending order .
1 <= k <= 1000
Example 1:
1 2 3 Input: nums1 = [1,7,11], nums2 = [2,4,6], k = 3 Output: [[1,2],[1,4],[1,6]] Explanation: The first 3 pairs are returned from the sequence: [1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]
Example 2:
1 2 3 Input: nums1 = [1,1,2], nums2 = [1,2,3], k = 2 Output: [[1,1],[1,1]] Explanation: The first 2 pairs are returned from the sequence: [1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3]
Example 3:
1 2 3 Input: nums1 = [1,2], nums2 = [3], k = 3 Output: [[1,3],[2,3]] Explanation: All possible pairs are returned from the sequence: [1,3],[2,3]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 vector <vector <int >> kSmallestPairs (vector <int >& nums1, vector <int >& nums2, int k) { auto cmp = [](auto & a, auto & b) { return a.first + a.second < b.first + b.second; }; vector <vector <int >> res; priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> pq(cmp); for (int num1 : nums1) { for (int num2 : nums2) { pq.push({num1, num2}); if (pq.size() > k) { pq.pop(); } } } while (!pq.empty()) { res.push_back({pq.top().first, pq.top().second}); pq.pop(); } return res; }
给定一个含有n
个正整数的数组和一个正整数target
。
找出该数组中满足其和≥ target
的长度最小的连续子数组[numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回0
。
Example 1:
1 2 3 Input: target = 7, nums = [2,3,1,2,4,3] Output: 2 Explanation: The subarray [4,3] has the minimal length under the problem constraint.
Example 2:
1 2 Input: target = 4, nums = [1,4,4] Output: 1
Example 3:
1 2 Input: target = 11, nums = [1,1,1,1,1,1,1,1] Output: 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 int minSubArrayLen (int target, vector <int >& nums) { vector <int > prefix (nums.size() + 1 ) ; for (int i = 0 ; i < nums.size(); i++) prefix[i + 1 ] = prefix[i] + nums[i]; int left = 0 , right = 0 ; int res = INT_MAX; while (right < nums.size()) { right++; while (prefix[right] - prefix[left] >= target) { res = min(res, right - left); left++; } } return res == INT_MAX ? 0 : res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int minSubArrayLen (int target, vector <int >& nums) { int left = 0 , right = 0 , sum = 0 ; int res = INT_MAX; while (right < nums.size()) { sum += nums[right]; right++; while (sum >= target) { res = min(res, right - left); sum -= nums[left]; left++; } } return res == INT_MAX ? 0 : res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 int minSubArrayLen (int target, vector <int >& nums) { vector <int > prefixSum (nums.size() + 1 , 0 ) ; for (int i = 1 ; i <= nums.size(); i++) prefixSum[i] = prefixSum[i - 1 ] + nums[i - 1 ]; int res = INT_MAX; for (int i = 0 ; i < nums.size(); i++) { int to_find = target + prefixSum[i]; int it = _lower_bound(prefixSum, to_find); if (it != prefixSum.size()) res = min(res, it - i); } return res == INT_MAX ? 0 : res; } int _lower_bound(vector <int >& nums, int target){ int lo = 0 , hi = nums.size() - 1 ; while (lo <= hi) { int mi = lo + (hi - lo >> 1 ); if (target <= nums[mi]) hi = mi - 1 ; else lo = mi + 1 ; } return lo; }
给你一个整数数组nums
,和一个表示限制的整数limit
,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于limit
。如果不存在满足条件的子数组,则返回0
。
1 <= nums.length <= 105
1 <= nums[i] <= 109
0 <= limit <= 109
Example 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 >Input: nums = [8,2,4,7], limit = 4 >Output: 2 >Explanation: All subarrays are: >[8] with maximum absolute diff |8-8| = 0 <= 4. >[8,2] with maximum absolute diff |8-2| = 6 > 4. >[8,2,4] with maximum absolute diff |8-2| = 6 > 4. >[8,2,4,7] with maximum absolute diff |8-2| = 6 > 4. >[2] with maximum absolute diff |2-2| = 0 <= 4. >[2,4] with maximum absolute diff |2-4| = 2 <= 4. >[2,4,7] with maximum absolute diff |2-7| = 5 > 4. >[4] with maximum absolute diff |4-4| = 0 <= 4. >[4,7] with maximum absolute diff |4-7| = 3 <= 4. >[7] with maximum absolute diff |7-7| = 0 <= 4. >Therefore, the size of the longest subarray is 2.
Example 2:
1 2 3 >Input: nums = [10,1,2,4,7,2], limit = 5 >Output: 4 >Explanation: The subarray [2,4,7,2] is the longest since the maximum absolute diff is |2-7| = 5 <= 5.
Example 3:
1 2 >Input: nums = [4,2,2,2,4,4,2,2], limit = 0 >Output: 3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int longestSubarray (vector <int >& nums, int limit) { multiset <int > setting; int res = 0 ; int left = 0 , right = 0 ; while (right < nums.size()) { setting.insert(nums[right++]); while (*setting.rbegin() - *setting.begin() > limit) setting.erase(setting.find(nums[left++])); res = max(res, right - left); } return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 int longestSubarray (vector <int >& nums, int limit) { deque <int > minQ; deque <int > maxQ; int res = 0 ; int left = 0 , right = 0 ; while (right < nums.size()) { while (!minQ.empty() && minQ.back() > nums[right]) minQ.pop_back(); while (!maxQ.empty() && maxQ.back() < nums[right]) maxQ.pop_back(); minQ.push_back(nums[right]); maxQ.push_back(nums[right]); right++; while (!minQ.empty() && !maxQ.empty() && (maxQ.front() - minQ.front() > limit)) { if (minQ.front() == nums[left]) minQ.pop_front(); if (maxQ.front() == nums[left]) maxQ.pop_front(); left++; } res = max(res, right - left); } return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 int longestSubarray (vector <int >& nums, int limit) { int res = 0 ; int minL = 0 , minR = -1 , maxL = nums.size(), maxR = nums.size() - 1 ; int l = 0 , r = 0 ; vector <int > ascending (nums.size()) ; while (r < nums.size()) { while (minR >= minL && nums[r] < ascending[minR]) minR--; while (maxR >= maxL && nums[r] > ascending[maxL]) maxL++; ascending[++minR] = nums[r]; ascending[--maxL] = nums[r]; r++; while (ascending[maxR] - ascending[minL] > limit) { if (nums[l] == ascending[minL]) minL++; if (nums[l] == ascending[maxR]) maxR--; l++; } res = max(res, r - l); } return res; }
给你一个整数数组nums
和两个整数k
和t
。请你判断是否存在两个不同下标i
和j
,使得abs(nums[i] - nums[j]) <= t
,同时又满足abs(i - j) <= k
。如果存在则返回true
,不存在返回false
。
Example 1:
1 2 Input: nums = [1,2,3,1], k = 3, t = 0 Output: true
Example 2:
1 2 Input: nums = [1,0,1,1], k = 1, t = 2 Output: true
Example 3:
1 2 Input: nums = [1,5,9,1,5,9], k = 2, t = 3 Output: false
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 bool containsNearbyAlmostDuplicate (vector <int >& nums, int k, int t) { set <long > ms; for (size_t i = 0 ; i < nums.size(); i++) { long valMin = (long )nums[i] - (long )t; auto iter = ms.lower_bound(valMin); if (iter != ms.end() && *iter <= (long )nums[i] + (long )t) return true ; ms.insert(nums[i]); if (ms.size() > k) ms.erase(nums[i - k]); } return false ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 bool containsNearbyAlmostDuplicate (vector <int >& nums, int k, int t) { long bucketsWidth = long (t) + 1 ; unordered_map <long , long > buckets; for (int i = 0 ; i < nums.size(); i++) { int id = getKey(nums[i], bucketsWidth); if (buckets.count(id)) return true ; if (buckets.count(id - 1 ) && nums[i] - buckets[id - 1 ] <= t) return true ; if (buckets.count(id + 1 ) && buckets[id + 1 ] - nums[i] <= t) return true ; buckets[id] = nums[i]; if (buckets.size() > k) buckets.erase(getKey(nums[i - k], bucketsWidth)); } return false ; } int getKey (int value, long bucketsWidth) { int id = value / bucketsWidth; if (value < 0 ) id--; return id; }
给定一个含有m x n
个元素的矩阵(m
行,n
列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。
Example 1:
1 2 Input: mat = [[1,2,3],[4,5,6],[7,8,9]] Output: [1,2,4,7,5,3,6,8,9]
Example 2:
1 2 Input: mat = [[1,2],[3,4]] Output: [1,2,3,4]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 vector <int > findDiagonalOrder (vector <vector <int >>& matrix) { if (matrix.empty()) return vector <int >(); int m = matrix.size(), n = matrix[0 ].size(); vector <vector <int >> v (m + n - 1 ) ; for (int i = 0 ; i < m; i++) for (int j = 0 ; j < n; j++) v[i + j].push_back(matrix[i][j]); vector <int > res; for (int i = 0 ; i < v.size(); i++) { if (i % 2 == 0 ) reverse(v[i].begin(), v[i].end()); res.insert(res.end(), v[i].begin(), v[i].end()); } return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 vector <int > findDiagonalOrder (vector <vector <int >>& matrix) { map <int , vector <int >> mapping; for (int i = 0 ; i < matrix.size(); i++) for (int j = 0 ; j < matrix[i].size(); j++) mapping[i + j].push_back(matrix[i][j]); vector <int > res; for (auto & p: mapping) { if (p.first % 2 == 0 ) res.insert(res.end(), p.second.rbegin(), p.second.rend()); else res.insert(res.end(), p.second.begin(), p.second.end()); } return res; }
给你一个列表num
,里面每一个元素都是一个整数列表。请你依照下面各图的规则,按顺序返回num
中对角线上的整数。
Example 1:
1 2 >Input: nums = [[1,2,3],[4,5,6],[7,8,9]] >Output: [1,4,2,7,5,3,8,6,9]
Example 2:
1 2 >Input: nums = [[1,2,3,4,5],[6,7],[8],[9,10,11],[12,13,14,15,16]] >Output: [1,6,2,8,7,3,9,4,12,10,5,13,11,14,15,16]
1 2 3 4 5 6 7 8 9 10 11 12 13 vector <int > findDiagonalOrder (vector <vector <int >>& nums) { map <int , vector <int >> mapping; for (int i = 0 ; i < nums.size(); i++) for (int j = 0 ; j < nums[i].size(); j++) mapping[i + j].push_back(nums[i][j]); vector <int > res; for (auto & p: mapping) res.insert(res.end(), p.second.rbegin(), p.second.rend()); return res; }
给你一个m
行n
列的矩阵matrix
,请按照顺时针螺旋顺序 ,返回矩阵中的所有元素。
Example 1:
1 2 Input: matrix = [[1,2,3],[4,5,6],[7,8,9]] Output: [1,2,3,6,9,8,7,4,5]
Example 2:
1 2 Input: matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]] Output: [1,2,3,4,8,12,11,10,9,5,6,7]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 vector <int > spiralOrder (vector <vector <int >>& matrix) { int m = matrix.size(); int n = matrix[0 ].size(); int u = 0 , d = m - 1 , l = 0 , r = n - 1 ; int p = 0 ; vector <int > order (m * n) ; while (u <= d && l <= r) { for (int col = l; col <= r; col++) order[p++] = matrix[u][col]; if (++u > d) break ; for (int row = u; row <= d; row++) order[p++] = matrix[row][r]; if (--r < l) break ; for (int col = r; col >= l; col--) order[p++] = matrix[d][col]; if (--d < u) break ; for (int row = d; row >= u; row--) order[p++] = matrix[row][l]; if (l++ > r) break ; } return order; }
Given a list of intervals
, remove all intervals that are covered by another interval in the list.
Interval [a,b)
is covered by interval [c,d)
if and only if c <= a
and b <= d
.
After doing so, return the number of remaining intervals .
Constraints:
1 <= intervals.length <= 1000
intervals[i].length == 2
0 <= intervals[i][0] < intervals[i][1] <= 10^5
All the intervals are unique .
Example 1:
1 2 3 Input: intervals = [[1,4],[3,6],[2,8]] Output: 2 Explanation: Interval [3,6] is covered by [2,8], therefore it is removed.
Example 2:
1 2 Input: intervals = [[1,4],[2,3]] Output: 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 int removeCoveredIntervals (vector <vector <int >>& intervals) { auto cmp = [](auto & a, auto & b){ return a[0 ] == b[0 ] ? b[1 ] < a[1 ] : a[0 ] < b[0 ]; }; sort(intervals.begin(), intervals.end(), cmp); vector <vector <int >> res; res.reserve(intervals.size()); res.push_back(intervals[0 ]); int left = intervals[0 ][0 ], right = intervals[0 ][1 ]; for (int i = 1 ; i < intervals.size(); i++) { auto & interval = intervals[i]; if (right >= interval[0 ] && right < interval[1 ]) { right = interval[1 ]; res.push_back(interval); } else if (right <= interval[0 ]) { left = interval[0 ]; right = interval[1 ]; res.push_back(interval); } } return res.size(); }
Given an array of intervals
where intervals[i] = [starti, endi]
, merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input .
Constraints:
1 <= intervals.length <= 104
intervals[i].length == 2
0 <= starti <= endi <= 104
Example 1:
1 2 3 Input: intervals = [[1,3],[2,6],[8,10],[15,18]] Output: [[1,6],[8,10],[15,18]] Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
Example 2:
1 2 3 Input: intervals = [[1,4],[4,5]] Output: [[1,5]] Explanation: Intervals [1,4] and [4,5] are considered overlapping.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 vector <vector <int >> merge (vector <vector <int >>& intervals) { auto cmp = [](auto & a, auto & b){ return a[0 ] == b[0 ] ? b[1 ] < a[1 ] : a[0 ] < b[0 ]; }; sort(intervals.begin(), intervals.end(), cmp); vector <vector <int >> res; int left = intervals[0 ][0 ], right = intervals[0 ][1 ]; for (int i = 1 ; i < intervals.size(); i++) { auto & interval = intervals[i]; if (right >= interval[0 ] && right <= interval[1 ]) right = interval[1 ]; else if (right < interval[0 ]) { res.push_back({left, right}); left = interval[0 ]; right = interval[1 ]; } } if (res.empty() || res.back() != vector <int >({left, right})) res.push_back({left, right}); return res; }
给你一个无重叠的 ,按照区间起始端点排序的区间列表。
在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
Example 1:
1 2 Input: intervals = [[1,3],[6,9]], newInterval = [2,5] Output: [[1,5],[6,9]]
Example 2:
1 2 3 Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8] Output: [[1,2],[3,10],[12,16]] Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10].
Example 3:
1 2 Input: intervals = [], newInterval = [5,7] Output: [[5,7]]
Example 4:
1 2 Input: intervals = [[1,5]], newInterval = [2,7] Output: [[1,7]]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 vector <vector <int >> insert (vector <vector <int >>& intervals, vector <int >& newInterval) { vector <vector <int >> res; int a1 = newInterval[0 ], b1 = newInterval[1 ]; bool found = false ; for (int i = 0 ; i < intervals.size(); i++) { int a2 = intervals[i][0 ], b2 = intervals[i][1 ]; if (b2 >= a1 && b1 >= a2) { a1 = min(a1, a2); b1 = max(b1, b2); } else if (b1 < a2 && !found) { res.push_back({a1, b1}); res.push_back({a2, b2}); found = true ; } else { res.push_back({a2, b2}); } } if (!found) res.push_back({a1, b1}); return res; }
给定两个由一些闭区间组成的列表,firstList
和secondList
,其中firstList[i] = [start_i, end_i]
而secondList[j] = [start_j, end_j]
。每个区间列表都是成对不相交的,并且已经排序。
返回这两个区间列表的交集 。
形式上,闭区间[a, b]
(其中a <= b
)表示实数x
的集合,而a <= x <= b
。
两个闭区间的交集是一组实数,要么为空集,要么为闭区间。例如,[1, 3]
和[2, 4]
的交集为[2, 3]
。
Example 1:
1 2 Input: firstList = [[0,2],[5,10],[13,23],[24,25]], secondList = [[1,5],[8,12],[15,24],[25,26]] Output: [[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]
Example 2:
1 2 Input: firstList = [[1,3],[5,9]], secondList = [] Output: []
Example 3:
1 2 Input: firstList = [], secondList = [[4,8],[10,12]] Output: []
Constraints:
0 <= firstList.length, secondList.length <= 1000
firstList.length + secondList.length >= 1
0 <= start_i < end_i <= 109
endi < start_(i + 1)
0 <= start_j < end_j <= 109
endj < start_(j + 1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 vector <vector <int >> intervalIntersection (vector <vector <int >>& firstList, vector <vector <int >>& secondList) { vector <vector <int >> res; int i = 0 , j = 0 ; while (i < firstList.size() && j < secondList.size()) { int a1 = firstList[i][0 ], b1 = firstList[i][1 ]; int a2 = secondList[j][0 ], b2 = secondList[j][1 ]; if (b1 >= a2 && b2 >= a1) res.push_back({max(a1, a2), min(b1, b2)}); if (b1 <= b2) i++; else j++; } return res; }
给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
注意:
可以认为区间的终点总是大于它的起点。
区间[1,2]
和[2,3]
的边界相互“接触”,但没有相互重叠。
Constraints:
1 <= intervals.size() <= 2 * 10^4
Example 1:
1 2 3 Input: intervals = [[1,2],[2,3],[3,4],[1,3]] Output: 1 Explanation: [1,3] can be removed and the rest of the intervals are non-overlapping.
Example 2:
1 2 3 Input: intervals = [[1,2],[1,2],[1,2]] Output: 2 Explanation: You need to remove two [1,2] to make the rest of the intervals non-overlapping.
Example 3:
1 2 3 Input: intervals = [[1,2],[2,3]] Output: 0 Explanation: You don't need to remove any of the intervals since they're already non-overlapping.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 int eraseOverlapIntervals (vector <vector <int >>& intervals) { sort(intervals.begin(), intervals.end()); int res = 0 ; int a1 = intervals[0 ][0 ], b1 = intervals[0 ][1 ]; for (int i = 1 ; i < intervals.size(); i++) { int a2 = intervals[i][0 ], b2 = intervals[i][1 ]; if (b2 > a1 && b1 > a2) { a1 = min(a1, a2); b1 = min(b1, b2); res++; } else { a1 = a2; b1 = b2; } } return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 int eraseOverlapIntervals (vector <vector <int >>& intervals) { auto cmp = [](vector <int >& a, vector <int >& b) { return a[1 ] < b[1 ]; }; sort(intervals.begin(), intervals.end(), cmp); int count = 0 ; int n = intervals.size(); int pre_end = intervals[0 ][1 ]; for (int i = 1 ; i < n; i++) { int start = intervals[i][0 ]; if (start < pre_end) count++; else pre_end = intervals[i][1 ]; } return count; }
在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以纵坐标并不重要,因此只要知道开始和结束的横坐标就足够了。开始坐标总是小于结束坐标。
一支弓箭可以沿着x
轴从不同点完全垂直地射出。在坐标x处射出一支箭,若有一个气球的直径的开始和结束坐标为xstart
,xend
, 且满足xstart ≤ x ≤ xend
,则该气球会被引爆。可以射出的弓箭的数量没有限制。 弓箭一旦被射出之后,可以无限地前进。我们想找到使得所有气球全部被引爆,所需的弓箭的最小数量。
给你一个数组points
,其中points [i] = [xstart, xend]
,返回引爆所有气球所必须射出的最小弓箭数。
Example 1:
1 2 3 Input: points = [[10,16],[2,8],[1,6],[7,12]] Output: 2 Explanation: One way is to shoot one arrow for example at x = 6 (bursting the balloons [2,8] and [1,6]) and another arrow at x = 11 (bursting the other two balloons).
Example 2:
1 2 Input: points = [[1,2],[3,4],[5,6],[7,8]] Output: 4
Example 3:
1 2 Input: points = [[1,2],[2,3],[3,4],[4,5]] Output: 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 int findMinArrowShots (vector <vector <int >>& points) { auto cmp = [](vector <int >& a, vector <int >& b) { return a[1 ] < b[1 ]; }; sort(points.begin(), points.end(), cmp); int count = 1 ; int n = points.size(); int pre_end = points[0 ][1 ]; for (int i = 1 ; i < n; i++) { int start = points[i][0 ]; if (start > pre_end) { count++; pre_end = points[i][1 ]; } } return count; }
给你一个区间数组intervals
,其中intervals[i] = [starti, endi]
,且每个starti
都不同 。
区间i
的右侧区间可以记作区间j
,并满足startj >= endi
,且startj
最小化 。
返回一个由每个区间i
的右侧区间的最小起始位置组成的数组。如果某个区间i
不存在对应的右侧区间,则下标i
处的值设为-1
。
Constraints:
1 <= intervals.length <= 2 * 10^4
intervals[i].length == 2
-10^6 <= starti <= endi <= 10^6
The start point of each interval is unique .
Example 1:
1 2 3 Input: intervals = [[1,2]] Output: [-1] Explanation: There is only one interval in the collection, so it outputs -1.
Example 2:
1 2 3 4 5 Input: intervals = [[3,4],[2,3],[1,2]] Output: [-1,0,1] Explanation: There is no right interval for [3,4]. The right interval for [2,3] is [3,4] since start0 = 3 is the smallest start that is >= end1 = 3. The right interval for [1,2] is [2,3] since start1 = 2 is the smallest start that is >= end2 = 2.
Example 3:
1 2 3 4 Input: intervals = [[1,4],[2,3],[3,4]] Output: [-1,2,-1] Explanation: There is no right interval for [1,4] and [3,4]. The right interval for [2,3] is [3,4] since start2 = 3 is the smallest start that is >= end1 = 3.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 vector <int > findRightInterval (vector <vector <int >>& intervals) { int n = intervals.size(); for (int i = 0 ; i < n; i++) intervals[i].push_back(i); sort(intervals.begin(), intervals.end()); vector <int > res (n, -1 ) ; for (int i = 0 ; i < n; i++) { for (int j = i; j < n; j++) { if (intervals[i][1 ] <= intervals[j][0 ]) { res[intervals[i][2 ]] = intervals[j][2 ]; break ; } } } return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 vector <int > findRightInterval (vector <vector <int >>& intervals) { int n = intervals.size(); for (int i = 0 ; i < n; i++) intervals[i].push_back(i); sort(intervals.begin(), intervals.end()); vector <int > res (n, -1 ) ; for (int i = 0 ; i < n; i++) { int index = left_bound(intervals, i, n, intervals[i]); if (index < n) res[intervals[i][2 ]] = intervals[index][2 ]; } return res; } int left_bound (vector <vector <int >>& intervals, int lo, int hi, vector <int >& interval) { while (lo < hi) { int mi = lo + ((hi - lo) >> 1 ); if (interval[1 ] <= intervals[mi][0 ]) hi = mi; else lo = mi + 1 ; } return lo; }
给定一个正整数数组nums
。找出该数组内乘积小于k
的连续的子数组的个数。
Example:
1 2 3 4 Input: nums = [10, 5, 2, 6], k = 100 Output: 8 Explanation: The 8 subarrays that have product less than 100 are: [10], [5], [2], [6], [10, 5], [5, 2], [2, 6], [5, 2, 6]. Note that [10, 5, 2] is not included as the product of 100 is not strictly less than k.
Note:
0 < nums.length <= 50000
.
0 < nums[i] < 1000
.
0 <= k < 10^6
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int numSubarrayProductLessThanK (vector <int >& nums, int k) { if (k <= 1 ) return 0 ; int left = 0 , right = 0 ; int product = 1 , count = 0 ; while (right < nums.size()) { product *= nums[right++]; while (product >= k) product /= nums[left++]; count += right - left; } return count; }
Given a binary array, find the maximum length of a contiguous subarray with equal number of 0 and 1.
解题方法说明图:
The following figure illustrates the observation for the sequence [0 0 1 0 0 0 1 1]
。
Example 1:
1 2 3 Input: [0,1] Output: 2 Explanation: [0, 1] is the longest contiguous subarray with equal number of 0 and 1.
Example 2:
1 2 3 Input: [0,1,0] Output: 2 Explanation: [0, 1] (or [1, 0]) is a longest contiguous subarray with equal number of 0 and 1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int findMaxLength (vector <int >& nums) { int n = nums.size(); unordered_map <int , int > mapping; mapping[0 ] = -1 ; int res = 0 , cnt = 0 ; for (int i = 0 ; i < n; i++) { cnt += nums[i] == 1 ? 1 : -1 ; if (mapping.count(cnt)) { res = max(res, i - mapping[cnt]); } else { mapping[cnt] = i; } } return res; }
给定一个包含n
个整数的数组nums
和一个目标值target
,判断nums
中是否存在四个元素a
,b
,c
和d
,使得a + b + c + d
的值与target
相等?找出所有满足条件且不重复的四元组。
注意:答案中不可以包含重复的四元组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 vector <vector <int >> fourSum (vector <int >& nums, int target) { return nTargetSum(nums, target, 4 ); } vector <vector <int >> nTargetSum (vector <int >& nums, int target, int n) { sort(nums.begin(), nums.end()); int len = nums.size(); vector <vector <int >> nSumResult; vector <int > curVals; auto twoSum = [&](int start, int target) { int lo = start, hi = len - 1 ; while (lo < hi) { int sum = nums[lo] + nums[hi]; int loVal = nums[lo], hiVal = nums[hi]; if (sum < target) { while (lo < hi && nums[lo] == loVal) { lo++; } } else if (target < sum) { while (lo < hi && nums[hi] == hiVal) { hi--; } } else { nSumResult.push_back({loVal, hiVal}); for (int val : curVals) { nSumResult.back().push_back(val); } while (lo < hi && nums[lo] == loVal) { lo++; } while (lo < hi && nums[hi] == hiVal) { hi--; } } } }; auto nSum = [&](auto && nSum, int start, int target, int n) { if (n <= 2 ) { twoSum(start, target); return ; } for (int i = start; i < len; i++) { curVals.push_back(nums[i]); nSum(nSum, i + 1 , target - nums[i], n - 1 ); curVals.pop_back(); while (i < len - 1 && nums[i] == nums[i + 1 ]) { i++; } } }; nSum(nSum, 0 , target, n); return nSumResult; }
数组中占比超过一半的元素称之为主要元素。给你一个整数数组,找出其中的主要元素。若没有,返回-1
。
请设计时间复杂度为O(n)
、空间复杂度为O(1)
的解决方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int majorityElement (vector <int >& nums) { int n = nums.size(); nth_element(nums.begin(), nums.begin() + n / 2 , nums.end()); int cnt = 0 ; for (int i = 0 ; i < n; i++) { if (nums[i] == nums[n / 2 ]) { cnt++; } } if (cnt > n/2 ) { return nums[n / 2 ]; } return -1 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 int majorityElement (vector <int >& nums) { int n = nums.size(); int cnt = 0 ; int lastNum = 0 ; for (int num : nums) { if (cnt == 0 ) { lastNum = num; cnt = 1 ; } else if (num == lastNum) { cnt++; } else { cnt--; } } cnt = 0 ; for (int num : nums) { if (num == lastNum) { cnt++; } } if (cnt > n/2 ) { return lastNum; } return -1 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 int majorityElement (vector <int >& nums) { int n = nums.size(); int res = 0 , cnt = 0 ; for (int i = 0 ; i < 32 ; i++) { int mask = (1 << i); cnt = 0 ; for (int num : nums) { if (num & mask) { cnt++; } } if (cnt > n/2 ) { res |= mask; } } cnt = 0 ; for (int num : nums) { if (num == res) { cnt++; } } if (cnt > n/2 ) { return res; } return -1 ; }
给你一个会议时间安排的数组intervals
,每个会议时间都会包括开始和结束的时间intervals[i] = [start_i, end_i]
,为避免会议冲突,同时要考虑充分利用会议室资源,请你计算至少需要多少间会议室,才能满足这些会议安排。
示例 1:
1 2 输入:intervals = [[0,30],[5,10],[15,20]] 输出:2
示例 2:
1 2 输入:intervals = [[7,10],[2,4]] 输出:1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int minMeetingRooms (vector <vector <int >>& intervals) { vector <pair<int , int >> times; for (auto && interval : intervals) { times.emplace_back(interval[0 ], 1 ); times.emplace_back(interval[1 ], -1 ); } sort(times.begin(), times.end()); int cnt = 0 , res = 0 ; for (auto && [_, flag] : times) { cnt += flag; res = max(res, cnt); } return res; }
假设你是一位顺风车司机,车上最初有capacity
个空座位可以用来载客。由于道路的限制,车只能向一个方向行驶(也就是说,不允许掉头或改变方向,你可以将其想象为一个向量)。
这儿有一份乘客行程计划表trips
[][],其中trips[i] = [num_passengers, start_location, end_location]
包含了第i
组乘客的行程信息:
Example 1:
1 2 Input: trips = [[2,1,5],[3,3,7]], capacity = 4 Output: false
Example 2:
1 2 Input: trips = [[2,1,5],[3,3,7]], capacity = 5 Output: true
Example 3:
1 2 Input: trips = [[2,1,5],[3,5,7]], capacity = 3 Output: true
Example 4:
1 2 Input: trips = [[3,2,7],[3,7,9],[8,3,9]], capacity = 11 Output: true
Constraints:
trips.length <= 1000
trips[i].length == 3
1 <= trips[i][0] <= 100
0 <= trips[i][1] < trips[i][2] <= 1000
1 <= capacity <= 100000
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 bool carPooling (vector <vector <int >>& trips, int capacity) { vector <int > passengers (1001 ) ; for (auto && trip : trips) { for (int i = trip[1 ]; i < trip[2 ]; i++) { passengers[i] += trip[0 ]; if (passengers[i] > capacity) { return false ; } } } return true ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 bool carPooling (vector <vector <int >>& trips, int capacity) { vector <int > diff (1001 ) ; for (auto && trip : trips) { diff[trip[1 ]] += trip[0 ]; diff[trip[2 ]] -= trip[0 ]; } for (int i = 1 ; i < 1000 ; i++) { diff[i] += diff[i - 1 ]; if (diff[i] > capacity) { return false ; } } return true ; }
在一座城市里,你需要建n
栋新的建筑。这些新的建筑会从1
到n
编号排成一列。
这座城市对这些新建筑有一些规定:
每栋建筑的高度必须是一个非负整数。
第一栋建筑的高度必须是0
。
任意两栋相邻建筑的高度差不能超过1
。
除此以外,某些建筑还有额外的最高高度限制。这些限制会以二维整数数组restrictions
的形式给出,其中restrictions[i] = [idi, maxHeighti]
,表示建筑idi
的高度 不能超过maxHeighti
。
题目保证每栋建筑在restrictions
中至多出现一次 ,同时建筑1
不会 出现在restrictions
中。
请你返回最高建筑能达到的最高高度 。
示例 1:
1 2 3 4 输入:n = 5, restrictions = [[2,1],[4,1]] 输出:2 解释:上图中的绿色区域为每栋建筑被允许的最高高度。 我们可以使建筑高度分别为 [0,1,2,1,2] ,最高建筑的高度为 2 。
示例 2:
1 2 3 4 输入:n = 6, restrictions = [] 输出:5 解释:上图中的绿色区域为每栋建筑被允许的最高高度。 我们可以使建筑高度分别为 [0,1,2,3,4,5] ,最高建筑的高度为 5 。
示例 3:
1 2 3 4 输入:n = 10, restrictions = [[5,3],[2,5],[7,4],[10,3]] 输出:5 解释:上图中的绿色区域为每栋建筑被允许的最高高度。 我们可以使建筑高度分别为 [0,1,2,3,3,4,4,5,4,3] ,最高建筑的高度为 5 。
Constraints:
2 <= n <= 10^9
0 <= restrictions.length <= min(n - 1, 10^5)
2 <= idi <= n
idi
is unique .
0 <= maxHeighti <= 10^9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 int maxBuilding (int n, vector <vector <int >>& r) { r.push_back({1 , 0 }); sort(r.begin(), r.end()); if (r.back()[0 ] != n) { r.push_back({n, n - 1 }); } int m = r.size(); for (int i = 1 ; i < m; i++) { r[i][1 ] = min(r[i][1 ], r[i - 1 ][1 ] + (r[i][0 ] - r[i - 1 ][0 ])); } for (int i = m - 2 ; i >= 0 ; i--) { r[i][1 ] = min(r[i][1 ], r[i + 1 ][1 ] + (r[i + 1 ][0 ] - r[i][0 ])); } int res = 0 ; for (int i = 0 ; i < m - 1 ; ++i) { int best = ((r[i + 1 ][0 ] - r[i][0 ]) + r[i][1 ] + r[i + 1 ][1 ]) / 2 ; res = max(res, best); } return res; }
元素的频数是该元素在一个数组中出现的次数。
给你一个整数数组nums
和一个整数k
。在一步操作中,你可以选择nums
的一个下标,并将该下标对应元素的值增加1
。
执行最多k
次操作后,返回数组中最高频元素的最大可能频数 。
Example 1:
1 2 3 4 Input: nums = [1,2,4], k = 5 Output: 3 Explanation: Increment the first element three times and the second element two times to make nums = [4,4,4]. 4 has a frequency of 3.
Example 2:
1 2 3 4 5 6 Input: nums = [1,4,8,13], k = 5 Output: 2 Explanation: There are multiple optimal solutions: - Increment the first element three times to make nums = [4,4,8,13]. 4 has a frequency of 2. - Increment the second element four times to make nums = [1,8,8,13]. 8 has a frequency of 2. - Increment the third element five times to make nums = [1,4,13,13]. 13 has a frequency of 2.
Example 3:
1 2 Input: nums = [3,9,6], k = 2 Output: 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 int maxFrequency (vector <int >& nums, int k) { sort(nums.begin(), nums.end(), greater<int >()); int n = nums.size(); int cnt = 0 ; for (int i = 0 ; i < n; i++) { int temp_k = k; int j = i + 1 ; for (; j < n; j++) { if (nums[i] - nums[j] <= temp_k) { temp_k -= nums[i] - nums[j]; } else { break ; } } cnt = max(cnt, j - i); } return cnt; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int maxFrequency (vector <int >& nums, int k) { sort(nums.begin(), nums.end()); long res = 0 , sum = 0 ; long left = 0 , right = 0 ; while (right < nums.size()) { sum += nums[right]; right++; while ((right - left) * nums[right - 1 ] > sum + k) { sum -= nums[left]; left++; } res = max(res, right - left); } return res; }
传送带上的包裹必须在days
天内从一个港口运送到另一个港口。
传送带上的第i
个包裹的重量为weights[i]
。每一天,我们都会按给出重量的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。
返回能在days
天内将传送带上的所有包裹送达的船的最低运载能力。
Example 1:
1 2 3 4 5 6 7 8 9 10 Input: weights = [1,2,3,4,5,6,7,8,9,10], D = 5 Output: 15 Explanation: A ship capacity of 15 is the minimum to ship all the packages in 5 days like this: 1st day: 1, 2, 3, 4, 5 2nd day: 6, 7 3rd day: 8 4th day: 9 5th day: 10 Note that the cargo must be shipped in the order given, so using a ship of capacity 14 and splitting the packages into parts like (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) is not allowed.
Example 2:
1 2 3 4 5 6 Input: weights = [3,2,2,4,1,4], D = 3 Output: 6 Explanation: A ship capacity of 6 is the minimum to ship all the packages in 3 days like this: 1st day: 3, 2 2nd day: 2, 4 3rd day: 1, 4
Example 3:
1 2 3 4 5 6 7 Input: weights = [1,2,3,1,1], D = 4 Output: 3 Explanation: 1st day: 1 2nd day: 2 3rd day: 3 4th day: 1, 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 int shipWithinDays (vector <int >& weights, int days) { auto computeDays = [&](int limit) { int days = 1 ; int load = 0 ; for (int weight : weights) { if (load + weight > limit) { days++; load = 0 ; } load += weight; } return days; }; int minLoad = *max_element(weights.begin(), weights.end()); int maxLoad = accumulate(weights.begin(), weights.end(), 0 ); while (minLoad < maxLoad) { int midLoad = minLoad + ((maxLoad - minLoad) >> 1 ); if (days >= computeDays(midLoad)) { maxLoad = midLoad; } else { minLoad = midLoad + 1 ; } } return minLoad; }
珂珂喜欢吃香蕉。这里有N
堆香蕉,第i
堆中有piles[i]
根香蕉。警卫已经离开了,将在hours
小时后回来。
珂珂可以决定她吃香蕉的速度K
(单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉K
根。如果这堆香蕉少于K
根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。
珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。
返回她可以在hours
小时内吃掉所有香蕉的最小速度K
(K
为整数)。
Example 1:
1 2 >Input: piles = [3,6,7,11], h = 8 >Output: 4
Example 2:
1 2 >Input: piles = [30,11,23,4,20], h = 5 >Output: 30
Example 3:
1 2 >Input: piles = [30,11,23,4,20], h = 6 >Output: 23
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 int minEatingSpeed (vector <int >& piles, int hours) { auto computeHours = [&](int speed) { int hours = 0 ; for (int pile : piles) { hours += (pile + speed - 1 ) / speed; } return hours; }; int minSpeed = 1 ; int maxSpeed = *max_element(piles.begin(), piles.end()) + 1 ; while (minSpeed < maxSpeed) { int midSpeed = minSpeed + ((maxSpeed - minSpeed) >> 1 ); if (hours >= computeHours(midSpeed)) { maxSpeed = midSpeed; } else { minSpeed = midSpeed + 1 ; } } return minSpeed; }
给你一个整数数组nums
,其中nums[i]
表示第i
个袋子里球的数目。同时给你一个整数maxOperations
。你可以进行如下操作至多maxOperations
次:
选择任意一个袋子,并将袋子里的球分到2
个新的袋子中,每个袋子里都有正整数个球。 比方说,一个袋子里有5
个球,你可以把它们分到两个新袋子里,分别有1
个和4
个球,或者分别有2
个和3
个球。
你的开销是单个袋子里球数目的最大值 ,你想要最小化开销。请你返回进行上述操作后的最小开销。
Example 1:
1 2 3 4 5 6 Input: nums = [9], maxOperations = 2 Output: 3 Explanation: - Divide the bag with 9 balls into two bags of sizes 6 and 3. [9] -> [6,3]. - Divide the bag with 6 balls into two bags of sizes 3 and 3. [6,3] -> [3,3,3]. The bag with the most number of balls has 3 balls, so your penalty is 3 and you should return 3.
Example 2:
1 2 3 4 5 6 7 8 Input: nums = [2,4,8,2], maxOperations = 4 Output: 2 Explanation: - Divide the bag with 8 balls into two bags of sizes 4 and 4. [2,4,8,2] -> [2,4,4,4,2]. - Divide the bag with 4 balls into two bags of sizes 2 and 2. [2,4,4,4,2] -> [2,2,2,4,4,2]. - Divide the bag with 4 balls into two bags of sizes 2 and 2. [2,2,2,4,4,2] -> [2,2,2,2,2,4,2]. - Divide the bag with 4 balls into two bags of sizes 2 and 2. [2,2,2,2,2,4,2] -> [2,2,2,2,2,2,2,2]. The bag with the most number of balls has 2 balls, so your penalty is 2 an you should return 2.
Example 3:
1 2 Input: nums = [7,17], maxOperations = 2 Output: 7
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 int minimumSize (vector <int >& nums, int maxOperations) { int minCost = 1 ; int maxCost = *max_element(nums.begin(), nums.end()) + 1 ; while (minCost < maxCost) { int midCost = minCost + (maxCost - minCost >> 1 ); int need = operations(nums, midCost); if (need <= maxOperations) { maxCost = midCost; } else { minCost = midCost + 1 ; } } return minCost; } int operations (vector <int >& nums, int cost) { int op = 0 ; for (int num : nums) { op += (num - 1 ) / cost; } return op; }
已知一个长度为n
的数组,预先按照升序排列,经由1
到n
次旋转后,得到输入数组。例如,原数组nums = [0,1,2,4,5,6,7]
在变化后可能得到: 若旋转4
次,则可以得到[4,5,6,7,0,1,2]
若旋转7
次,则可以得到[0,1,2,4,5,6,7]
注意,数组[a[0], a[1], a[2], ..., a[n-1]]
旋转一次的结果为数组[a[n-1], a[0], a[1], a[2], ..., a[n-2]]
。
给你一个元素值互不相同 的数组nums
,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的最小元素 。
Example 1:
1 2 3 Input: nums = [3,4,5,1,2] Output: 1 Explanation: The original array was [1,2,3,4,5] rotated 3 times.
Example 2:
1 2 3 Input: nums = [4,5,6,7,0,1,2] Output: 0 Explanation: The original array was [0,1,2,4,5,6,7] and it was rotated 4 times.
Example 3:
1 2 3 Input: nums = [11,13,15,17] Output: 11 Explanation: The original array was [11,13,15,17] and it was rotated 4 times.
Constraints:
1 <= nums.length <= 5000
All the integers of nums
are unique .
nums
is sorted and rotated between 1
and nums.length
times.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int findMin (vector <int >& nums) { int n = nums.size(); int lo = 0 , hi = n - 1 ; while (lo < hi) { int mi = lo + (hi - lo >> 1 ); if (nums[mi] <= nums[hi]) { hi = mi; } else { lo = mi + 1 ; } } return nums[lo]; }
已知一个长度为n
的数组,预先按照升序排列,经由1
到n
次旋转后,得到输入数组。例如,原数组nums = [0,1,2,4,5,6,7]
在变化后可能得到: 若旋转4
次,则可以得到[4,5,6,7,0,1,2]
若旋转7
次,则可以得到[0,1,2,4,5,6,7]
注意,数组[a[0], a[1], a[2], ..., a[n-1]]
旋转一次的结果为数组[a[n-1], a[0], a[1], a[2], ..., a[n-2]]
。
给你一个可能存在重复元素值 的数组nums
,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的最小元素 。
Example 1:
1 2 Input: nums = [1,3,5] Output: 1
Example 2:
1 2 Input: nums = [2,2,2,0,1] Output: 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int findMin (vector <int >& nums) { int n = nums.size(); int lo = 0 , hi = n - 1 ; while (lo < hi) { int mi = lo + (hi - lo >> 1 ); if (nums[mi] < nums[hi]) { hi = mi; } else if (nums[mi] > nums[hi]) { lo = mi + 1 ; } else { hi--; } } return nums[lo]; }
整数数组nums
按升序排列,数组中的值互不相同 。给你旋转后 的数组nums
和一个整数target
,如果nums
中存在这个目标值target
,则返回它的下标,否则返回-1
。
Example 1:
1 2 Input: nums = [4,5,6,7,0,1,2], target = 0 Output: 4
Example 2:
1 2 Input: nums = [4,5,6,7,0,1,2], target = 3 Output: -1
Example 3:
1 2 Input: nums = [1], target = 0 Output: -1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 int search (vector <int >& nums, int target) { int lo = 0 , hi = nums.size() - 1 ; while (lo <= hi) { int mi = lo + (hi - lo >> 1 ); if (target == nums[mi]) { return mi; } if (nums[mi] >= nums[lo]) { if (target < nums[mi] && target >= nums[lo]) { hi = mi - 1 ; } else { lo = mi + 1 ; } } else { if (target > nums[mi] && target <= nums[hi]) { lo = mi + 1 ; } else { hi = mi - 1 ; } } } return -1 ; }
已知存在一个按非降序排列 的整数数组nums
,数组中的值不必互不相同 。
给你旋转后的数组nums
和一个整数target
,请你编写一个函数来判断给定的目标值是否存在于数组中。如果nums
中存在这个目标值target
,则返回true
,否则返回false
。
Example 1:
1 2 Input: nums = [2,5,6,0,0,1,2], target = 0 Output: true
Example 2:
1 2 Input: nums = [2,5,6,0,0,1,2], target = 3 Output: false
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 int search (vector <int >& nums, int target) { int lo = 0 , hi = nums.size() - 1 ; while (lo <= hi) { int mi = lo + (hi - lo >> 1 ); if (target == nums[mi]) { return true ; } if (nums[lo] == nums[mi] && nums[mi] == nums[hi]) { lo++; hi--; } else if (nums[mi] >= nums[lo]) { if (target < nums[mi] && target >= nums[lo]) { hi = mi - 1 ; } else { lo = mi + 1 ; } } else { if (target > nums[mi] && target <= nums[hi]) { lo = mi + 1 ; } else { hi = mi - 1 ; } } } return false ; }
Given a binary array nums
and an integer k
, return the maximum number of consecutive 1
‘s in the array if you can flip at most k
0
‘s.
Example 1:
1 2 3 Input: nums = [1,1,1,0,0,0,1,1,1,1,0], k = 2 Output: 6 Explanation: [1,1,1,0,0,1,1,1,1,1,1]
Example 2:
1 2 3 Input: nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], k = 3 Output: 10 Explanation: [0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 int longestOnes (vector <int >& nums, int k) { int res = 0 ; int left = 0 , right = 0 ; int zeros = 0 ; while (right < nums.size()) { zeros += 1 - nums[right++]; while (zeros > k) { zeros += nums[left++] - 1 ; } res = max(res, right - left); } return res; } int longestOnes (vector <int >& nums, int k) { int l = 0 , r = 0 ; while (r < nums.size()) { k += nums[r++] - 1 ; if (k < 0 ) k += 1 - nums[l++]; } return r - l; }
给出飞机的起飞和降落时间,用interval
序列表示,请计算出天上同时最多有多少架飞机?
如果多架飞机降落和起飞在同一时刻,我们认为降落有优先权。
样例 1:
1 2 3 4 5 6 7 8 >输入: [[1, 10], [2, 3], [5, 8], [4, 7] >输出: 3 >解释: >第一架飞机在 1 时刻起飞, 10 时刻降落. >第二架飞机在 2 时刻起飞, 3 时刻降落. >第三架飞机在 5 时刻起飞, 8 时刻降落. >第四架飞机在 4 时刻起飞, 7 时刻降落. >在 5 时刻到 6 时刻之间, 天空中有三架飞机.
样例 2:
1 2 3 >输入: [[1, 2], [2, 3], [3, 4]] >输出: 1 >解释: 降落优先于起飞.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int countOfAirplanes (vector <vector <int >> &airplanes) { vector <pair<int , int >> timeSeries; for (auto & interval : airplanes) { timeSeries.push_back({interval[0 ], 1 }); timeSeries.push_back({interval[1 ], -1 }); } sort(timeSeries.begin(), timeSeries.end()); int count = 0 , res = 0 ; for (auto && [_, p] : timeSeries) { count += p; res = max(res, count); } return res; }
城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。给你所有建筑物的位置和高度,请返回由这些建筑物形成的天际线 。
每个建筑物的几何信息由数组buildings
表示,其中三元组buildings[i] = [lefti, righti, heighti]
表示:
lefti
是第i
座建筑物左边缘的x
坐标。
righti
是第i
座建筑物右边缘的x
坐标。
heighti
是第i座建筑物的高度。
天际线应该表示为由 “关键点” 组成的列表,格式[[x1,y1],[x2,y2],...]
,并按x
坐标进行排序 。关键点是水平线段的左端点。列表中最后一个点是最右侧建筑物的终点,y
坐标始终为0
,仅用于标记天际线的终点。此外,任何两个相邻建筑物之间的地面都应被视为天际线轮廓的一部分。
注意:输出天际线中不得有连续的相同高度的水平线。例如[...[2 3], [4 5], [7 5], [11 5], [12 7]...]
是不正确的答案;三条高度为5
的线应该在最终输出中合并为一个:[...[2 3], [4 5], [12 7], ...]
示例:
1 2 3 4 5 输入:buildings = [[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]] 输出:[[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]] 解释: 图 A 显示输入的所有建筑物的位置和高度, 图 B 显示由这些建筑物形成的天际线。图 B 中的红点表示输出列表中的关键点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 vector <vector <int >> getSkyline (vector <vector <int >>& buildings) { vector <pair<int , int >> geometrixPoints; for (auto && building : buildings) { geometrixPoints.emplace_back(building[0 ], 0 - building[2 ]); geometrixPoints.emplace_back(building[1 ], building[2 ]); } sort(geometrixPoints.begin(), geometrixPoints.end()); multiset <int > heights; heights.insert(0 ); int maxHeight = 0 ; vector <vector <int >> keyPoints; for (auto && [x_pos, height] : geometrixPoints) { if (height < 0 ) { heights.insert(abs (height)); } else { heights.erase(heights.find(height)); } int curMaxHeight = *heights.rbegin(); if (curMaxHeight != maxHeight) { keyPoints.emplace_back(vector {{x_pos, curMaxHeight}}); maxHeight = curMaxHeight; } } return keyPoints; }
给定两个大小分别为m
和n
的有序 (从小到大)数组nums1
和nums2
。请你找出并返回这两个正序数组的中位数 。
进阶: 你能设计一个时间复杂度为O(log(m+n))
的算法解决此问题吗?
Example 1:
1 2 3 Input: nums1 = [1,3], nums2 = [2] Output: 2.00000 Explanation: merged array = [1,2,3] and median is 2.
Example 2:
1 2 3 Input: nums1 = [1,2], nums2 = [3,4] Output: 2.50000 Explanation: merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5.
Example 3:
1 2 Input: nums1 = [0,0], nums2 = [0,0] Output: 0.00000
Example 4:
1 2 Input: nums1 = [], nums2 = [1] Output: 1.00000
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 double findMedianSortedArrays (vector <int >& nums1, vector <int >& nums2) { int m = nums1.size(), n = nums2.size(); vector <int > merged (m + n) ; int i = 0 , j = 0 , k = 0 ; while (i < m || j < n) { if (j >= n || (i < m && nums1[i] < nums2[j])) { merged[k++] = nums1[i++]; } else { merged[k++] = nums2[j++]; } } return double (merged[(m + n) / 2 ] + merged[(m + n - 1 ) / 2 ]) / 2 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 double findMedianSortedArrays (vector <int >& nums1, vector <int >& nums2) { int m = nums1.size(), n = nums2.size(); int i = 0 , j = 0 ; int preValue = 0 , curValue = 0 ; while ((i < m || j < n) && (i + j) <= (m + n) / 2 ) { preValue = curValue; if (j >= n || (i < m && nums1[i] < nums2[j])) { curValue = nums2[i++]; } else { curValue = nums2[j++]; } } return (m + n) & 1 ? curValue : double (preValue + curValue) / 2 ; }
存在一个不含0
的环形数组nums
,每个nums[i]
都表示位于下标i
的角色应该向前或向后移动的下标个数:
如果nums[i]
是正数,向前移动nums[i]
步
如果nums[i]
是负数,向后移动nums[i]
步
因为数组是环形的,所以可以假设从最后一个元素向前移动一步会到达第一个元素,而第一个元素向后移动一步会到达最后一个元素。
数组中的循环由长度为k的下标序列seq
:
遵循上述移动规则将导致重复下标序列seq[0] -> seq[1] -> ... -> seq[k - 1] -> seq[0] -> ...
所有nums[seq[j]]
应当不是全正就是全负
k > 1
如果nums
中存在循环,返回true
;否则,返回false
。
Example 1:
1 2 3 4 5 Input: nums = [2,-1,1,2,2] Output: true Explanation: There is a cycle from index 0 -> 2 -> 3 -> 0 -> ... The cycle's length is 3.
Example 2:
1 2 3 4 5 Input: nums = [-1,2] Output: false Explanation: The sequence from index 1 -> 1 -> 1 -> ... is not a cycle because the sequence's length is 1. By definition the sequence's length must be strictly greater than 1 to be a cycle.
Example 3:
1 2 3 4 5 Input: nums = [-2,1,-1,-2,-2] Output: false Explanation: The sequence from index 1 -> 2 -> 1 -> ... is not a cycle because nums[1] is positive, but nums[2] is negative. Every nums[seq[j]] must be either all positive or all negative.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 bool circularArrayLoop (vector <int >& nums) { int n = nums.size(); auto getnext = [&](int i) { return ((i + nums[i]) % n + n) % n; }; for (int i = 0 ; i < n; i++) { if (nums[i] == 0 ) continue ; int slow = i, fast = i; while (nums[i] * nums[getnext(fast)] > 0 && nums[i] * nums[getnext(getnext(fast))] > 0 ) { slow = getnext(slow); fast = getnext(getnext(fast)); if (slow == fast) { if (slow == getnext(slow)) break ; return true ; } } slow = i; while (nums[i] * nums[slow] > 0 ) { int temp = getnext(slow); nums[slow] = 0 ; slow = temp; } } return false ; }
给你一个未排序的整数数组nums
,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为O(n)
并且只使用常数级别额外空间的解决方案。
参考题解 :缺失的第一个正数 - 缺失的第一个正数
Example 1:
1 2 Input: nums = [1,2,0] Output: 3
Example 2:
1 2 Input: nums = [3,4,-1,1] Output: 2
Example 3:
1 2 Input: nums = [7,8,9,11,12] Output: 1
Constraints:
1 <= nums.length <= 300
-2^31 <= nums[i] <= 2^31 - 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int firstMissingPositive (vector <int >& nums) { int n = nums.size(); unordered_set <int > setting; for (int num : nums) { setting.insert(num); } for (int i = 1 ; i <= n; i++) { if (!setting.count(i)) { return i; } } return n + 1 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 int firstMissingPositive (vector <int >& nums) { int n = nums.size(); for (int i = 0 ; i < n; i++) { if (nums[i] <= 0 ) { nums[i] = n + 1 ; } } for (int i = 0 ; i < n; i++) { int num = abs (nums[i]); if (num <= n && nums[num - 1 ] > 0 ) { nums[num - 1 ] *= -1 ; } } for (int i = 0 ; i < n; i++) { if (nums[i] > 0 ) { return i + 1 ; } } return n + 1 ; }
给你一个整数数组bloomDay
,以及两个整数m
和k
。现需要制作m
束花。制作花束时,需要使用花园中相邻的k
朵花 。花园中有n
朵花,第i
朵花会在bloomDay[i]
时盛开,恰好可以用于一束花中。请你返回从花园中摘m
束花需要等待的最少的天数。如果不能摘到m
束花则返回-1
。
Example 1:
1 2 3 4 5 6 7 Input: bloomDay = [1,10,3,10,2], m = 3, k = 1 Output: 3 Explanation: Let's see what happened in the first three days. x means flower bloomed and _ means flower didn't bloom in the garden. We need 3 bouquets each should contain 1 flower. After day 1: [x, _, _, _, _] // we can only make one bouquet. After day 2: [x, _, _, _, x] // we can only make two bouquets. After day 3: [x, _, x, _, x] // we can make 3 bouquets. The answer is 3.
Example 2:
1 2 3 Input: bloomDay = [1,10,3,10,2], m = 3, k = 2 Output: -1 Explanation: We need 3 bouquets each has 2 flowers, that means we need 6 flowers. We only have 5 flowers so it is impossible to get the needed bouquets and we return -1.
Example 3:
1 2 3 4 5 6 7 8 Input: bloomDay = [7,7,7,7,12,7,7], m = 2, k = 3 Output: 12 Explanation: We need 2 bouquets each should have 3 flowers. Here's the garden after the 7 and 12 days: After day 7: [x, x, x, x, _, x, x] We can make one bouquet of the first three flowers that bloomed. We cannot make another bouquet from the last three flowers that bloomed because they are not adjacent. After day 12: [x, x, x, x, x, x, x] It is obvious that we can make two bouquets in different ways.
Example 4:
1 2 3 Input: bloomDay = [1000000000,1000000000], m = 1, k = 1 Output: 1000000000 Explanation: You need to wait 1000000000 days to have a flower ready for a bouquet.
Example 5:
1 2 Input: bloomDay = [1,10,2,9,3,8,4,7,5,6], m = 4, k = 2 Output: 9
Constraints:
bloomDay.length == n
1 <= n <= 10^5
1 <= bloomDay[i] <= 10^9
1 <= m <= 10^6
1 <= k <= n
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 int minDays (vector <int >& bloomDay, int m, int k) { if (m > bloomDay.size() / k) return -1 ; auto [minVal, maxVal] = minmax_element(bloomDay.begin(), bloomDay.end()); int lo = *minVal, hi = *maxVal; while (lo <= hi) { int mi = lo + (hi - lo) / 2 ; if (canMake(bloomDay, m, k, mi)) hi = mi - 1 ; else lo = mi + 1 ; } return lo; } bool canMake (vector <int >& bloomDay, int m, int k, int days) { int flowers = 0 ; for (int i = 0 ; i < bloomDay.size() && m > 0 ; i++) { if (bloomDay[i] > days) { flowers = 0 ; } else { flowers++; if (flowers == k) { m--; flowers = 0 ; } } } return m == 0 ; }
这里有n
个航班,它们分别从1
到n
进行编号。
有一份航班预订表bookings
,表中第i
条预订记录bookings[i] = [first_i, last_i, seats_i]
意味着在从first_i
到last_i
(包含first_i
和last_i
)的每个航班上预订了seats_i
个座位。
请你返回一个长度为n
的数组answer
,其中answer[i]
是航班i
上预订的座位总数。
Example 1:
1 2 3 4 5 6 7 8 9 Input: bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5 Output: [10,55,45,25,25] Explanation: Flight labels: 1 2 3 4 5 Booking 1 reserved: 10 10 Booking 2 reserved: 20 20 Booking 3 reserved: 25 25 25 25 Total seats: 10 55 45 25 25 Hence, answer = [10,55,45,25,25]
Example 2:
1 2 3 4 5 6 7 8 Input: bookings = [[1,2,10],[2,2,15]], n = 2 Output: [10,25] Explanation: Flight labels: 1 2 Booking 1 reserved: 10 10 Booking 2 reserved: 15 Total seats: 10 25 Hence, answer = [10,25]
Constraints:
1 <= n <= 2 * 10^4
1 <= bookings.length <= 2 * 10^4
bookings[i].length == 3
1 <= firsti <= lasti <= n
1 <= seatsi <= 10^4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class Difference {private : vector <int > diff; public : Difference(const vector <int >& nums) { int n = nums.size(); diff.resize(n); for (int i = 0 ; i < n; i++) { if (i == 0 ) { diff[i] = nums[i]; } else { diff[i] = nums[i] - nums[i - 1 ]; } } } void add (int i, int j, int val) { diff[i] += val; if (j + 1 < diff.size()) { diff[j + 1 ] -= val; } } vector <int > result () { vector <int > res (diff.size()) ; res[0 ] = diff[0 ]; for (int i = 1 ; i < diff.size(); i++) { res[i] = res[i - 1 ] + diff[i]; } return res; } }; vector <int > corpFlightBookings (vector <vector <int >>& bookings, int n) { vector <int > diff (n) ; Difference difference (diff) ; for (auto & booking : bookings) { int i = booking[0 ] - 1 ; int j = booking[1 ] - 1 ; int val = booking[2 ]; difference.add(i, j, val); } return difference.result(); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 vector <int > corpFlightBookings (vector <vector <int >>& bookings, int n) { vector <int > difference (n) ; for (auto && booking : bookings) { int i = booking[0 ] - 1 ; int j = booking[1 ] - 1 ; int val = booking[2 ]; difference[i] += val; if (j + 1 < n) { difference[j + 1 ] -= val; } } for (int i = 1 ; i < n; i++) { difference[i] += difference[i - 1 ]; } return difference; }
在仅包含0
和1
的数组A
中,一次K
位翻转包括选择一个长度为K
的(连续)子数组,同时将子数组中的每个0
更改为1
,而每个1
更改为0
。
返回所需的k
位翻转的最小次数,以便数组没有值为0
的元素。如果不可能,返回-1
。
xample 1:
1 2 3 Input: A = [0,1,0], K = 1 Output: 2 Explanation: Flip A[0], then flip A[2].
Example 2:
1 2 3 Input: A = [1,1,0], K = 2 Output: -1 Explanation: No matter how we flip subarrays of size 2, we can't make the array become [1,1,1].
Example 3:
1 2 3 4 5 6 Input: A = [0,0,0,1,0,1,1,0], K = 3 Output: 3 Explanation: Flip A[0],A[1],A[2]: A becomes [1,1,1,1,0,1,1,0] Flip A[4],A[5],A[6]: A becomes [1,1,1,1,1,0,0,0] Flip A[5],A[6],A[7]: A becomes [1,1,1,1,1,1,1,1]
Note:
1 <= A.length <= 30000
1 <= K <= A.length
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 int minKBitFlips (vector <int >& A, int K) { int n = A.size(); int i = 0 , cnt = 0 ; while (1 ) { while (i < n && A[i] != 0 ) i++; if (i == n) break ; if (i + K > n) return -1 ; for (int j = 0 ; j < K; j++) A[i + j] = 1 - A[i + j]; cnt++; } return cnt; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int minKBitFlips (vector <int >& A, int K) { int n = A.size(); int cnt = 0 , sum = 0 ; vector <int > diff (n + 1 ) ; for (int i = 0 ; i < n; i++) { if (i > 0 ) diff[i] += diff[i - 1 ]; if ((A[i] + diff[i]) % 2 == 0 ) { if (i + K > n) return -1 ; diff[i] += 1 ; diff[i + K] -= 1 ; cnt++; } } return cnt; }
给你一个数组nums
,请你完成两类查询,其中一类查询要求更新数组下标对应的值,另一类查询要求返回数组中某个范围内元素的总和。
实现NumArray
类:
NumArray(int[] nums)
:用整数数组nums
初始化对象
void update(int index, int val)
:将nums[index]
的值更新为val
int sumRange(int left, int right)
:返回子数组nums[left, right]
的总和(即,nums[left] + nums[left + 1], ..., nums[right]
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 class NumArray { public : NumArray(vector <int >& nums) : _nums(nums), bit(_nums.size()) { for (int i = 0 ; i < _nums.size(); i++) add(i + 1 , _nums[i]); } void update (int index, int val) { add(index + 1 , val - _nums[index]); _nums[index] = val; } int sumRange (int left, int right) { return getsum(right + 1 ) - getsum(left); } private : vector <int > _nums; vector <int > bit; int lowbit (int x) { return x & (-x); } void add (int pos, int val) { for (int i = pos; i <= bit.size(); i += lowbit(i)) bit[i - 1 ] += val; } int getsum (int pos) { int res = 0 ; for (int i = pos; i > 0 ; i -= lowbit(i)) res += bit[i - 1 ]; return res; } };
有一个正整数数组arr
,现给你一个对应的查询数组queries
,其中queries[i] = [Li, Ri]
。
对于每个查询i
,请你计算从Li
到Ri
的XOR
值(即arr[Li] xor arr[Li+1] xor ... xor arr[Ri]
)作为本次查询的结果。并返回一个包含给定查询queries
所有结果的数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 vector <int > bit;int lowbit (int x) { return x & (-x); } void add (int pos, int val) { for (; pos <= bit.size(); pos += lowbit(pos)) bit[pos - 1 ] ^= val; } int getsum (int pos) { int res; for (; pos > 0 ; pos -= lowbit(pos)) res ^= bit[pos - 1 ]; return res; } vector <int > xorQueries (vector <int >& arr, vector <vector <int >>& queries) { bit.resize(arr.size()); for (int i = 0 ; i < arr.size(); i++) add(i + 1 , arr[i]); vector <int > res; for (auto & query : queries) res.push_back(getsum(query[1 ] + 1 ) ^ getsum(query[0 ])); return res; }
给定一个整数数组nums
,按要求返回一个新数组counts
。数组counts
有该性质:counts[i]
的值是nums[i]
右侧小于nums[i]
的元素的数量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 class Bit {private : int n; vector <int > bit; int lowbit (int x) { return x & (-x); } public : Bit(int _n) : n(_n), bit(n + 1 ) { } void add (int pos, int val) { while (pos <= n) { bit[pos] += val; pos += lowbit(pos); } } int getsum (int pos) { int sum = 0 ; while (pos > 0 ) { sum += bit[pos]; pos -= lowbit(pos); } return sum; } }; vector <int > countSmaller (vector <int >& nums) { int n = nums.size(); vector <int > temp (nums) ; sort(temp.begin(), temp.end()); for (int i = 0 ; i < n; i++) { nums[i] = lower_bound(temp.begin(), temp.end(), nums[i]) - temp.begin() + 1 ; } Bit bit (n) ; vector <int > res; for (int i = n - 1 ; i >= 0 ; i--) { res.push_back(bit.getsum(nums[i] - 1 )); bit.add(nums[i], 1 ); } reverse(res.begin(), res.end()); return res; }
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数 。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 class Bit {private : int n; vector <int > bit; int lowbit (int x) { return x & (-x); } public : Bit(int _n) : n(_n), bit(n + 1 ) { } void add (int pos, int val) { while (pos <= n) { bit[pos] += val; pos += lowbit(pos); } } int getsum (int pos) { int sum = 0 ; while (pos > 0 ) { sum += bit[pos]; pos -= lowbit(pos); } return sum; } }; int reversePairs (vector <int >& nums) { int n = nums.size(); vector <int > temp (nums) ; sort(temp.begin(), temp.end()); unordered_map <int , int > mapping; int i = 1 ; for (int num : temp) { mapping[num] = i++; } Bit bit (n) ; int res = 0 ; for (int i = n - 1 ; i >= 0 ; i--) { res += bit.getsum(mapping[nums[i]] - 1 ); bit.add(mapping[nums[i]], 1 ); } return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 int reversePairs (vector <int > data) { int n = data.size(); int cnt = 0 ; vector <int > helper (n/2 +1 ) ; auto merge = [&](int lo, int mi, int hi) { for (int i = mi + 1 ; i <= hi; i++) { helper[i - mi - 1 ] = data[i]; } int i = mi; int j = hi - mi - 1 ; int k = hi; while (i >= lo && j >= 0 ) { if (data[i] > helper[j]) { data[k--] = data[i--]; cnt += j + 1 ; } else { data[k--] = helper[j--]; } } while (j >= 0 ) { data[k--] = helper[j--]; } }; function<void (int , int )> mergeSort = [&](int lo, int hi) { if (lo >= hi) { return ; } int mi = lo + (hi - lo) / 2 ; mergeSort(lo, mi); mergeSort(mi + 1 , hi); merge(lo, mi, hi); }; mergeSort(0 , n - 1 ); return cnt; }
给你一个整数数组nums
。
现需要从数组中取三个下标i
、j
和k
,其中(0 <= i < j <= k < nums.size())
。
a
和b
定义如下:
a = nums[i] ^ nums[i + 1] ^ ... ^ nums[j - 1]
b = nums[j] ^ nums[j + 1] ^ ... ^ nums[k]
请返回能够令a == b
成立的三元组(i, j , k)
的数目。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int countTriplets (vector <int >& nums) { int n = nums.size(); vector <int > prefix (n + 1 ) ; for (int i = 1 ; i <= n; i++) prefix[i] = prefix[i - 1 ] ^ nums[i - 1 ]; int res = 0 ; for (int i = 0 ; i < n; i++) for (int j = i + 1 ; j < n; j++) for (int k = j; k < n; k++) if (prefix[j] ^ prefix[i] == prefix[k + 1 ] ^ prefix[j]) res++; return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int countTriplets (vector <int >& nums) { int n = nums.size(); vector <int > prefix (n + 1 ) ; for (int i = 1 ; i <= n; i++) prefix[i] = prefix[i - 1 ] ^ nums[i - 1 ]; int res = 0 ; for (int i = 0 ; i < n; i++) for (int k = i + 1 ; k < n; k++) if (prefix[i] == prefix[k + 1 ]) res += k - i; return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 int countTriplets (vector <int > &nums) { int n = nums.size(); vector <int > prefix (n + 1 ) ; for (int i = 1 ; i <= n; i++) prefix[i] = prefix[i - 1 ] ^ nums[i - 1 ]; unordered_map <int , int > cnt, total; int res = 0 ; for (int k = 0 ; k < n; ++k) { if (cnt.count(prefix[k + 1 ])) res += cnt[prefix[k + 1 ]] * k - total[prefix[k + 1 ]]; cnt[prefix[k]]++; total[prefix[k]] += k; } return res; }
给你一个整数数组nums
,返回nums[i] ^ nums[j]
的最大运算结果,其中0 ≤ i ≤ j < n
。
进阶 :你可以在O(n)
的时间解决这个问题吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 struct Trie { Trie* child[2 ] = {nullptr , nullptr }; }; Trie* root = new Trie; void insert (int num) { Trie* cur = root; for (int i = 30 ; i >= 0 ; i--) { int a = (num >> i) & 1 ; if (!cur->child[a]) cur->child[a] = new Trie; cur = cur->child[a]; } } int check (int num) { Trie* cur = root; int res = 0 ; for (int i = 30 ; i >= 0 ; i--) { int a = (num >> i) & 1 ; int b = 1 - a; if (cur->child[b]) { res |= (b << i); cur = cur->child[b]; } else { res |= (a << i); cur = cur->child[a]; } } return res; } int findMaximumXOR (vector <int >& nums) { int res = 0 ; for (int num : nums) { insert(num); res = max(res, num ^ check(num)); } return res; }
给你一个由非负整数组成的数组nums
。另有一个查询数组queries
,其中queries[i] = [xi, mi]
。
第i
个查询的答案是xi
和任何nums
数组中不超过mi
的元素按位异或得到的最大值。换句话说,答案是max(nums[j] XOR xi)
,其中所有j
均满足nums[j] <= mi
。如果nums
中的所有元素都大于mi
,最终答案就是-1
。
返回一个整数数组answer
作为查询的答案,其中answer.length == queries.length
且answer[i]
是第i
个查询的答案。
题解 :与数组中元素的最大异或值 - 与数组中元素的最大异或值 - 力扣(LeetCode)
Example:
1 2 3 4 5 6 Input: nums = [0,1,2,3,4], queries = [[3,1],[1,3],[5,6]] Output: [3,3,7] Explanation: 1) 0 and 1 are the only two integers not greater than 1. 0 XOR 3 = 3 and 1 XOR 3 = 2. The larger of the two is 3. 2) 1 XOR 2 = 3. 3) 5 XOR 2 = 7.
Constraints:
1 <= nums.length, queries.length <= 10^5
queries[i].length == 2
0 <= nums[j], xi, mi <= 10^9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 class Solution { public : vector <int > maximizeXor (vector <int >& nums, vector <vector <int >>& queries) { for (int num : nums) insert(num); vector <int > res; res.reserve(queries.size()); for (auto query : queries) res.push_back(getVal(query[0 ], query[1 ])); return res; } private : struct Trie { int minVal = INT_MAX; Trie* child[2 ] = {nullptr , nullptr }; }; Trie* root = new Trie; void insert (int num) { root->minVal = min(root->minVal, num); Trie* cur = root; for (int i = 30 ; i >= 0 ; i--) { int bit = (num >> i) & 1 ; if (!cur->child[bit]) cur->child[bit] = new Trie; cur->child[bit]->minVal = min(cur->child[bit]->minVal, num); cur = cur->child[bit]; } } int getVal (int num, int m) { if (m < root->minVal) return -1 ; Trie* cur = root; int res = 0 ; for (int i = 30 ; i >= 0 ; i--) { int bit = (num >> i) & 1 ; if (cur->child[bit ^ 1 ] && cur->child[bit ^ 1 ]->minVal <= m) { res |= (1 << i); bit = bit ^ 1 ; } cur = cur->child[bit]; } return res; } };
给出矩阵matrix
和目标值target
,返回元素总和等于目标值的非空子矩阵的数量。
如果(x1, y1, x2, y2)
和(x1', y1', x2', y2')
两个子矩阵中部分坐标不同(如:x1 != x1'
),那么这两个子矩阵也不同。
题解 :【宫水三叶】优化枚举的基本思路与进阶内容 - 元素和为目标值的子矩阵数量 - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 int numSubmatrixSumTarget (vector <vector <int >>& matrix, int target) { int m = matrix.size(); int n = matrix[0 ].size(); vector <vector <int >> prefixsumOfSubMatrix (m + 1 , vector <int >(n + 1 )) ; for (int i = 1 ; i <= m; i++) for (int j = 1 ; j <= n; j++) prefixsumOfSubMatrix[i][j] = matrix[i - 1 ][j - 1 ] + prefixsumOfSubMatrix[i - 1 ][j] + prefixsumOfSubMatrix[i][j - 1 ] - prefixsumOfSubMatrix[i - 1 ][ j - 1 ]; int res = 0 ; for (int rl = 1 ; rl <= m; rl++) for (int cu = 1 ; cu <= n; cu ++) for (int rr = rl; rr <= m; rr++) for (int cd = cu; cd <= n; cd++) if (prefixsumOfSubMatrix[rr][cd] - prefixsumOfSubMatrix[rr][cu - 1 ] - prefixsumOfSubMatrix[rl - 1 ][cd] + prefixsumOfSubMatrix[rl - 1 ][cu - 1 ] == target) res++; return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 int numSubmatrixSumTarget (vector <vector <int >> &matrix, int target) { int m = matrix.size(), n = matrix[0 ].size(); int res = 0 ; for (int i = 0 ; i < m; ++i) { vector <int > sum (n) ; for (int j = i; j < m; ++j) { for (int c = 0 ; c < n; ++c) sum[c] += matrix[j][c]; res += sumsOfSubArrayEqualTarget(sum, target); } } return res; } int sumsOfSubArrayEqualTarget (vector <int >& nums, int target) { unordered_map <int , int > mapping; mapping[0 ] = 1 ; int res = 0 , preSum = 0 ; for (int num : nums) { preSum += num; if (mapping.count(preSum - target)) res += mapping[preSum - target]; ++mapping[preSum]; } return res; }
给你一个二维矩阵matrix
和一个整数k
,矩阵大小为m x n
由非负整数组成。矩阵中坐标(a, b)
的值可由对所有满足0 <= i <= a < m
且0 <= j <= b < n
的元素matrix[i][j]
(下标从0
开始计数)执行异或运算得到。
请你找出matrix
的所有坐标中第k
大的值(k
的值从1
开始计数)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int kthLargestValue (vector <vector <int >>& matrix, int k) { int m = matrix.size(); int n = matrix[0 ].size(); vector <vector <int >> subMatrixXors (m + 1 , vector <int >(n + 1 )) ; priority_queue<int , vector <int >, greater<int >> pq; for (int i = 1 ; i <= m; i++) { for (int j = 1 ; j <= n; j++) { subMatrixXors[i][j] = subMatrixXors[i - 1 ][j - 1 ] ^ subMatrixXors[i][j - 1 ] ^ subMatrixXors[i - 1 ][j] ^ matrix[i - 1 ][j - 1 ]; pq.push(subMatrixXors[i][j]); if (pq.size() > k) pq.pop(); } } return pq.top(); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int kthLargestValue (vector <vector <int >>& matrix, int k) { int m = matrix.size(); int n = matrix[0 ].size(); vector <vector <int >> subMatrixXors (m + 1 , vector <int >(n + 1 )) ; vector <int > temp; temp.reserve(m * n); for (int i = 1 ; i <= m; i++) { for (int j = 1 ; j <= n; j++) { subMatrixXors[i][j] = subMatrixXors[i - 1 ][j - 1 ] ^ subMatrixXors[i][j - 1 ] ^ subMatrixXors[i - 1 ][j] ^ matrix[i - 1 ][j - 1 ]; temp.push_back(subMatrixXors[i][j]); } } nth_element(temp.begin(), prev(temp.end(), k), temp.end()); return temp[m * n - k]; }
给你一个整数数组nums
,你需要找出一个连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。请你找出符合题意的最短子数组,并输出它的长度。
Example 1:
1 2 3 Input: nums = [2,6,4,8,10,9,15] Output: 5 Explanation: You need to sort [6, 4, 8, 10, 9] in ascending order to make the whole array sorted in ascending order.
Example 2:
1 2 Input: nums = [1,2,3,4] Output: 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int findUnsortedSubarray (vector <int >& nums) { vector <int > temp (nums) ; sort(temp.begin(), temp.end()); int left = -1 , right = -2 ; for (int i = 0 ; i < nums.size(); i++) { if (nums[i] != temp[i]) { if (left == -1 ) { left = i; } right = i; } } return right - left + 1 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int findUnsortedSubarray (vector <int >& nums) { int n = nums.size(); int res = 0 , left = INT_MAX, right = 0 ; for (int i = 0 ; i < n; i++) { for (int j = i; j < n; j++) { if (nums[j] < nums[i]) { left = min(left, i); right = max(right, j); } } } return left == INT_MAX ? 0 : right - left + 1 ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 int findUnsortedSubarray (vector <int >& nums) { int n = nums.size(); int left = -1 , right = -2 ; int maximun = INT_MIN; for (int i = 0 ; i < n; i++) { if (nums[i] < maximun) { right = i; } else { maximun = nums[i]; } } int minimum = INT_MAX; for (int i = n - 1 ; i >= 0 ; i--) { if (nums[i] > minimum) { left = i; } else { minimum = nums[i]; } } return right - left + 1 ; }
给定一个n × n
的二维矩阵matrix
表示一个图像。请你将图像顺时针旋转90
度。你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
示例 1:
1 2 输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]] 输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]
1 2 3 4 5 6 7 8 9 10 void rotate (vector <vector <int >>& matrix) { int n = matrix.size(); vector <vector <int >> res (matrix) ; for (int i = 0 ; i < n; i++) { for (int j = 0 ; j < n; j++) { matrix[j][n - i - 1 ] = res[i][j]; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void rotate (vector <vector <int >>& matrix) { int n = matrix.size(); for (int i = 0 ; i < n / 2 ; i++) { for (int j = 0 ; j < n; j++) { swap(matrix[i][j], matrix[n - i - 1 ][j]); } } for (int i = 0 ; i < n; i++) { for (int j = 0 ; j < i; j++) { swap(matrix[i][j], matrix[j][i]); } } }
给你一个整数数组nums
,你的目标是令nums
中的所有元素相等。完成一次减少操作需要遵照下面的几个步骤:
参考题解 :使数组元素相等的减少操作次数 - 使数组元素相等的减少操作次数 - 力扣(LeetCode)
示例 1:
1 2 3 4 5 6 7 输入:nums = [5,1,3] 输出:3 解释:需要 3 次操作使 nums 中的所有元素相等: 1. largest = 5 下标为 0 。nextLargest = 3 。将 nums[0] 减少到 3 。nums = [3,1,3] 。 2. largest = 3 下标为 0 。nextLargest = 1 。将 nums[0] 减少到 1 。nums = [1,1,3] 。 3. largest = 3 下标为 2 。nextLargest = 1 。将 nums[2] 减少到 1 。nums = [1,1,1] 。
示例 3:
1 2 3 4 5 6 7 8 输入:nums = [1,1,2,2,3] 输出:4 解释:需要 4 次操作使 nums 中的所有元素相等: 1. largest = 3 下标为 4 。nextLargest = 2 。将 nums[4] 减少到 2 。nums = [1,1,2,2,2] 。 2. largest = 2 下标为 2 。nextLargest = 1 。将 nums[2] 减少到 1 。nums = [1,1,1,2,2] 。 3. largest = 2 下标为 3 。nextLargest = 1 。将 nums[3] 减少到 1 。nums = [1,1,1,1,2] 。 4. largest = 2 下标为 4 。nextLargest = 1 。将 nums[4] 减少到 1 。nums = [1,1,1,1,1] 。
提示:
1 <= nums.length <= 5 * 10^4
1 <= nums[i] <= 5 * 10^4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int reductionOperations (vector <int >& nums) { sort(nums.begin(), nums.end()); int n = nums.size(); int res = 0 ; int cnt = 0 ; for (int i = 1 ; i < n; ++i) { if (nums[i] != nums[i-1 ]) { ++cnt; } res += cnt; } return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int reductionOperations (vector <int >& nums) { sort(nums.begin(), nums.end(), greater<int >()); vector <int > count; int i = 0 , n = nums.size(); while (i < n) { int max_value = nums[i]; int cnt = 0 ; while (i < n && nums[i] == max_value) { cnt++; i++; } count.push_back(cnt); } count.pop_back(); partial_sum(count.begin(), count.end(), count.begin()); return accumulate(count.begin(), count.end(), 0 ); }
集合s
包含从1
到n
的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制成了集合里面的另外一个数字的值,导致集合丢失了一个数字并且有一个数字重复。
给定一个数组nums
代表了集合s
发生错误后的结果。请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
示例 1 :
1 2 输入:nums = [1,2,2,4] 输出:[2,3]
提示 :
2 <= nums.length <= 1e4
1 <= nums[i] <= 1e4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 vector <int > findErrorNums (vector <int >& nums) { int n = nums.size(); unordered_set <int > existed; vector <int > res (2 ) ; for (int num : nums) { if (existed.count(num)) { res[0 ] = num; } existed.insert(num); } for (int i = 1 ; i <= n; i++) { if (existed.count(i) == 0 ) { res[1 ] = i; } } return res; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 vector <int > findErrorNums (vector <int >& nums) { int n = nums.size(); int a = 0 , b = 0 ; for (int i = 0 ; i < n; i++) { int num = abs (nums[i]); if (nums[num - 1 ] < 0 ) { a = num; } else { nums[num - 1 ] *= -1 ; } } for (int i = 0 ; i < n; i++) { if (nums[i] > 0 ) { b = i + 1 ; } } return {a, b}; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 vector <int > findErrorNums (vector <int >& nums) { int n = nums.size(); int sum = (1 + n) * n / 2 ; int sum_1 = 0 , sum_2 = 0 ; vector <bool > sets (n + 1 ) ; for (int num : nums) { sum_1 += num; if (!sets[num]) { sum_2 += num; } sets[num] = true ; } return {sum_1 - sum_2, sum - sum_2}; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 vector <int > findErrorNums (vector <int >& nums) { int n = nums.size(); int xors = 0 ; for (int i = 0 ; i < n; i++) { xors = xors ^ (i + 1 ) ^ nums[i]; } int lowbit = xors & (-xors); int a = 0 , b = 0 ; for (int i = 0 ; i < n; i++) { if (nums[i] & lowbit) { a = a ^ nums[i]; } else { b = b ^ nums[i]; } if ((i + 1 ) & lowbit) { a = a ^ (i + 1 ); } else { b = b ^ (i + 1 ); } } for (int num : nums) { if (a == num) { return {a, b}; } } return {b, a}; }
给定一个非空整数数组,找到使所有数组元素相等所需的最小操作数,其中每次操作可将选定的一个元素加1
或减1
。
参考题解 :
C++|中位数|简单证明 - 最少移动次数使数组元素相等 II
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 int minMoves2 (vector <int >& nums) { int n = nums.size(); _nth_element(nums, n/2 ); int midVal = nums[n/2 ]; int res = 0 ; for (int num : nums) { res += abs (num - midVal); } return res; } void _nth_element(vector <int >& nums, int k) { auto shuffle = [&](int lo, int hi) { for (int i = lo; i <= hi; i++) { int j = rand() % (hi - i + 1 ) + i; swap(nums[i], nums[j]); } }; auto partition = [&](int lo, int hi) { shuffle(lo, hi); int i = lo, j = lo; while (++j <= hi) { if (nums[j] < nums[lo]) { swap(nums[++i], nums[j]); } } swap(nums[lo], nums[i]); return i; }; int lo = 0 , hi = int (nums.size()) - 1 ; while (lo <= hi) { int mi = lo + ((hi - lo) >> 1 ); int p = partition(lo, hi); if (p == k) { return ; } else if (p < k) { lo = p + 1 ; } else { hi = p - 1 ; } } }
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
参考链接 :下一个排列算法详解:思路+推导+步骤,看不懂算我输
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void nextPermutation (vector <int >& nums) { int n = nums.size(); int left = n - 2 ; while (left >= 0 && nums[left] >= nums[left + 1 ]) { left--; } if (left >= 0 ) { int right = n - 1 ; while (right >= 0 && nums[right] <= nums[left]) { right--; } swap(nums[left], nums[right]); } reverse(next(nums.begin(), left + 1 ), nums.end()); }
给定一个未排序的整数数组nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为O(n)
的算法解决此问题。
示例 1:
1 2 3 输入:nums = [100,4,200,1,3,2] 输出:4 解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 int longestConsecutive (vector <int >& nums) { int n = nums.size(); if (n == 0 ) { return 0 ; } sort(nums.begin(), nums.end()); unique(nums.begin(), nums.end()); int res = 0 , cnt = 1 ; for (int i = 1 ; i < n; i++) { if (nums[i] == nums[i - 1 ] + 1 ) { cnt++; } else { res = max(res, cnt); cnt = 1 ; } } return max(res, cnt); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int longestConsecutive (vector <int >& nums) { unordered_set <int > existed; for (int num : nums) { existed.insert(num); } int res = 0 ; for (int num : existed) { if (existed.count(num - 1 ) == 0 ) { int maxVal = num; while (existed.count(maxVal + 1 )) { maxVal++; } res = max(res, maxVal - num + 1 ); } } return res; }
你这个学期必须选修n
门课程,记为0
到n - 1
。在选修某些课程之前需要一些先修课程。 先修课程按数组p
给出,其中p[i] = [ai, bi]
,表示如果要学习课程ai
则必须先学习课程bi
。例如,先修课程对[0, 1]
表示:想要学习课程0
,你需要先完成课程1
。
请你判断是否可能完成所有课程的学习?如果可以,返回true
;否则,返回false
。
示例:
1 2 3 输入:n = 2, p = [[1,0],[0,1]] 输出:false 解释:总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 bool canFinish (int n, vector <vector <int >>& p) { vector <vector <int >> adj (n) ; vector <int > in (n) ; for (auto && v : p) { adj[v[1 ]].push_back(v[0 ]); in[v[0 ]]++; } queue <int > q; for (int i = 0 ; i < n; i++) { if (in[i] == 0 ) { q.push(i); } } vector <int > res; while (!q.empty()) { int from = q.front(); q.pop(); res.push_back(from); for (auto to : adj[from]) { in[to]--; if (in[to] == 0 ) { q.push(to); } } } return res.size() == n; }
你总共需要上n
门课,课程编号依次为0
到n-1
。有的课会有直接的先修课程,比如如果想上课程0
,你必须先上课程1
,那么会以[1, 0]
数对的形式给出先修课程数对。
给你课程总数n
和一个直接先修课程数对列表p
和一个查询对列表q
。
对于每个查询对q[i]
,请判断q[i][0]
是否是q[i][1]
的先修课程。请返回一个布尔值列表,列表中每个元素依次分别对应q
每个查询对的判断结果。
注意:如果课程a
是课程b
的先修课程且课程b
是课程c
的先修课程,那么课程a
也是课程c
的先修课程。
参考链接 :图最短路径算法之弗洛伊德算法(Floyd) | Echo Blog
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 vector <bool > checkIfPrerequisite (int n, vector <vector <int >>& p, vector <vector <int >>& q) { vector <vector <bool >> adj (n, vector <bool >(n)) ; for (auto && v : p) { adj[v[0 ]][v[1 ]] = true ; } for (int k = 0 ; k < n; k++) { for (int i = 0 ; i < n; i++) { for (int j = 0 ; j < n; j++) { adj[i][j] = adj[i][j] || (adj[i][k] && adj[k][j]); } } } vector <bool > res; for (auto && v : q) { res.push_back(adj[v[0 ]][v[1 ]]); } return res; }
给定一个m x n
整数矩阵matrix
,找出其中最长递增路径的长度。对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到 边界外(即不允许环绕)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 int longestIncreasingPath (vector <vector <int >>& matrix) { int m = matrix.size(), n = matrix[0 ].size(); vector <vector <int >> adj (m * n) ; vector <int > in (m * n) ; auto getId = [n](int i, int j) { return i * n + j; }; vector <int > memo (m * n, -1 ) ; auto dfs = [&](auto && dfs, int from) { if (adj[from].empty()) { return 1 ; } if (memo[from] != -1 ) { return memo[from]; } int len = 0 ; for (auto to : adj[from]) { len = max(len, 1 + dfs(dfs, to)); } return memo[from] = len; }; for (int i = 0 ; i < m; i++) { for (int j = 0 ; j < n; j++) { if (i + 1 < m && matrix[i][j] < matrix[i + 1 ][j]) { adj[getId(i, j)].push_back(getId(i + 1 , j)); in[getId(i + 1 , j)]++; } if (j + 1 < n && matrix[i][j] < matrix[i][j + 1 ]) { adj[getId(i, j)].push_back(getId(i, j + 1 )); in[getId(i, j + 1 )]++; } if (i - 1 >= 0 && matrix[i][j] < matrix[i - 1 ][j]) { adj[getId(i, j)].push_back(getId(i - 1 , j)); in[getId(i - 1 , j)]++; } if (j - 1 >= 0 && matrix[i][j] < matrix[i][j - 1 ]) { adj[getId(i, j)].push_back(getId(i, j - 1 )); in[getId(i, j - 1 )]++; } } } int res = 1 ; for (int i = 0 ; i < m * n; i++) { if (in[i] == 0 ) { res = max(res, dfs(dfs, i)); } } return res; }
验证原始的序列org
是否可以从序列集seqs
中唯一地重建。序列org
是1
到n
整数的排列,其中1 ≤ n ≤ 10^4
。重建是指在序列集seqs
中构建最短的公共超序列。(即使得所有seqs
中的序列都是该最短序列的子序列)。确定是否只可以从seqs
重建唯一的序列,且该序列就是org
。
示例 1 :
1 2 3 4 输入: org: [1,2,3], seqs: [[1,2],[1,3]] 输出:false 解释:[1,2,3] 不是可以被重建的唯一的序列,因为 [1,3,2] 也是一个合法的序列。
示例 2 :
1 2 3 输入:org: [1,2,3], seqs: [[1,2]] 输出:false 解释:可以重建的序列只有 [1,2]。
示例 3 :
1 2 3 输入:org: [1,2,3], seqs: [[1,2],[1,3],[2,3]] 输出:true 解释:序列 [1,2], [1,3] 和 [2,3] 可以被唯一地重建为原始的序列 [1,2,3]。
示例 4 :
1 2 输入:org: [4,1,5,2,6,3], seqs: [[5,2,6,3],[4,1,5,2]] 输出:true
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 bool sequenceReconstruction (vector <int >& org, vector <vector <int >>& seqs) { if (seqs.empty()) { return false ; } int n = org.size(); vector <int > in (n + 1 ) ; vector <vector <int >> adj (n + 1 ) ; unordered_set <int > all_set; for (auto && seq : seqs) { int m = seq.size(); for (int i = 0 ; i < m; i++) { if (seq[i] <= 0 || seq[i] > n) { return false ; } if (i == 0 ) { all_set.insert(seq[i]); continue ; } int from = seq[i - 1 ]; int to = seq[i]; adj[from].push_back(to); in[to]++; all_set.insert(to); } } vector <int > res; queue <int > q; for (int i = 1 ; i <= n; i++) { if (in[i] == 0 ) { q.push(i); } } while (!q.empty()) { if (q.size() > 1 ) { return false ; } int from = q.front(); q.pop(); res.push_back(from); for (int to : adj[from]) { in[to]--; if (in[to] == 0 ) { q.push(to); } } } return org == res; }