给你一个数组 arr ,请你将每个元素用它右边最大的元素替换,如果是最后一个元素,用 -1 替换。
完成所有替换操作后,请你返回这个数组。
示例:
输入:arr = [17,18,5,4,6,1]
输出:[18,6,6,6,1,-1]
提示:
\(1 <= arr.length <= 10^4\)
\(1 <= arr[i] <= 10^5\)
Solution
从后往前扫描,并且记录最大值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution {public : vector <int > replaceElements(vector <int >& arr) { const int n = arr.size(); int maxa = arr[n-1 ]; arr[n-1 ] = -1 ; for (int i = n-2 ; i >= 0 ; i--) { int temp = arr[i]; arr[i] = maxa; if (maxa < temp) maxa = temp; } return arr; } };
给你一个整数数组 arr 和一个目标值 target ,请你返回一个整数 value ,使得将数组中所有大于 value 的值变成 value 后,数组的和最接近 target (最接近表示两者之差的绝对值最小)。
如果有多种使得和最接近 target 的方案,请你返回这些整数中的最小值。
请注意,答案不一定是 arr 中的数字。
示例 1:
输入:arr = [4,9,3], target = 10
输出:3
解释:当选择 value 为 3 时,数组会变成 [3, 3, 3],和为 9 ,这是最接近 target 的方案。
Solution
先排序,然后前缀和预处理 arr 数组,然后从 0 开始遍历答案,因为 arr 已经排序了,所以计算差异的时候使用二分。总的时间复杂度是 \(O(nlogn)\)
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 class Solution {public : int findBestValue (vector <int >& arr, int target) { const int n = arr.size(); sort(arr.begin(), arr.end()); int psum[n+1 ], r = -1 ; psum[0 ] = 0 ; for (int i = 1 ; i <= n; i++) { psum[i] = psum[i-1 ] + arr[i-1 ]; r = max(r, arr[i-1 ]); } int diff = 100000000 ; for (int i = 0 ; i <= r+1 ; i++) { int pos = lower_bound(arr.begin(), arr.end(), i) - arr.begin(); int temp = psum[pos]+(n-pos)*i; int last = diff; diff = abs (temp-target); if (diff >= last) return i-1 ; } return -1 ; } };
给你一棵二叉树,请你返回层数最深的叶子节点的和。
Solution
BFS 遍历记录每一层椰子节点的和,遍历完成也就是最深的叶子结点。
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 class Solution {public : int deepestLeavesSum (TreeNode* root) { queue <TreeNode*> q; q.push(root); int sum; while (!q.empty()) { int n = q.size(); sum = 0 ; for (int i = 0 ; i < n; i++) { TreeNode* top = q.front(); q.pop(); sum += top->val; if (top->left != NULL ) q.push(top->left); if (top->right != NULL ) q.push(top->right); } } return sum; } };
给你一个正方形字符数组 board ,你从数组最右下方的字符 'S'
出发。
你的目标是到达数组最左上角的字符 'E' ,数组剩余的部分为数字字符 1, 2, ..., 9
或者障碍 'X'
。在每一步移动中,你可以向上、向左或者左上方移动,可以移动的前提是到达的格子没有障碍。
一条路径的 「得分」 定义为:路径上所有数字的和。
请你返回一个列表,包含两个整数:第一个整数是 「得分」 的最大值,第二个整数是得到最大得分的方案数,请把结果对 \(10^9 + 7\) 取余。
如果没有任何路径可以到达终点,请返回 [0, 0] 。
示例 1:
输入:board = ["E23","2X2","12S"] 输出:[7,1]
Solution
这题用动态规划做还是比较明显的,第一问有点类似动态规划的经典入门题 数字三角形 。熟悉动态规划的话转移方程的话比较容易想到 \[
dp[i][j] = \max \{ dp[i-1][j-1], max \{ dp[i-1][k], dp[i][j-1] \} \} \quad i, j \in (0, 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 52 53 54 class Solution {public : vector <int > pathsWithMaxScore(vector <string >& board) { const int n = board.size(); const int mod = 1000000007 ; int dp[n+1 ][n+1 ]; int dp1[n+1 ][n+1 ]; memset (dp, 0 , sizeof dp); memset (dp1, 0 , sizeof dp1); dp1[0 ][0 ] = 1 ; board[n-1 ][n-1 ]= '0' ; for (int i = 1 ; i < n; i++) { if (board[0 ][i] != 'X' ) { dp[0 ][i] = dp[0 ][i-1 ]+board[0 ][i]-'0' ; dp1[0 ][i] = 1 ; } else break ; } for (int i = 1 ; i < n; i++) { if (board[i][0 ] != 'X' ) { dp[i][0 ] = dp[i-1 ][0 ]+board[i][0 ]-'0' ; dp1[i][0 ] = 1 ; } else break ; } for (int i = 1 ; i < n; i++) for (int j = 1 ; j < n; j++) { if (board[i][j] != 'X' ) { int a = dp[i-1 ][j]; int b = dp[i-1 ][j-1 ]; int c = dp[i][j-1 ]; int temp = max(a, max(b, c)); dp[i][j] = temp+board[i][j]-'0' ; if (temp == 0 && dp1[i-1 ][j] == 0 && dp1[i-1 ][j-1 ] == 0 && dp1[i][j-1 ] == 0 ) { dp[i][j] = 0 ; dp1[i][j] = 0 ; continue ; } if (a == temp) dp1[i][j] += dp1[i-1 ][j]%mod; if (b == temp) dp1[i][j] += dp1[i-1 ][j-1 ]%mod; if (c == temp) dp1[i][j] += dp1[i][j-1 ]%mod; } } return {dp[n-1 ][n-1 ], dp1[n-1 ][n-1 ]%mod}; } };