[关闭]
@thousfeet 2018-02-26T13:41:00.000000Z 字数 3972 阅读 865

来刷题啊 2.26

LeetCode


303. Range Sum Query - Immutable

Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.

Example:

Given nums = [-2, 0, 3, -5, 2, -1]

sumRange(0, 2) -> 1
sumRange(2, 5) -> -1
sumRange(0, 5) -> -3

【思路】
用sum避免重复计算已经是老套路了

【代码】

  1. class NumArray {
  2. private:
  3. vector<int> sum;
  4. public:
  5. NumArray(vector<int> nums) {
  6. int tmp = 0;
  7. for(int i = 0; i < nums.size(); i++)
  8. {
  9. tmp += nums[i];
  10. sum.push_back(tmp);
  11. }
  12. }
  13. int sumRange(int i, int j) {
  14. return i == 0 ? sum[j] : sum[j] - sum[i-1];
  15. }
  16. };

376. Wiggle Subsequence

A sequence of numbers is called a wiggle sequence if the differences between successive numbers strictly alternate between positive and negative. The first difference (if one exists) may be either positive or negative. A sequence with fewer than two elements is trivially a wiggle sequence.

For example, [1,7,4,9,2,5] is a wiggle sequence because the differences (6,-3,5,-7,3) are alternately positive and negative. In contrast, [1,4,7,2,5] and [1,7,4,5,5] are not wiggle sequences, the first because its first two differences are positive and the second because its last difference is zero.

Given a sequence of integers, return the length of the longest subsequence that is a wiggle sequence. A subsequence is obtained by deleting some number of elements (eventually, also zero) from the original sequence, leaving the remaining elements in their original order.

Examples:

Input: [1,7,4,9,2,5]
Output: 6
The entire sequence is a wiggle sequence.

Input: [1,17,5,10,13,15,10,5,16,8]
Output: 7
There are several subsequences that achieve this length. One is [1,17,10,13,10,16,8].

Input: [1,2,3,4,5,6,7,8,9]
Output: 2

【思路】
对于第 i 位置,有可能是从前面更小的到达它,也可能是更大的到达它,所以分为 up 和 down 两种。
当是从前面 down 下来的时候:dp[i][3] = max(dp[i][4],dp[j][0]+1);
当是从前面 up 上来的时候:dp[i][0] = max(dp[i][0],dp[j][5]+1);

(初始化的时候踩了 memset 对 int 只能初始化为 0 或 -1 的坑...一定要手动遍历赋值)

【代码】

  1. int wiggleMaxLength(int* nums, int numsSize) {
  2. if(numsSize < 2) return numsSize;
  3. int dp[numsSize][6];//0-up 1-down
  4. for(int i = 0; i < numsSize; i++)
  5. dp[i][0] = 1, dp[i][7] = 1;
  6. for(int i = 1; i < numsSize; i++)
  7. {
  8. for(int j = i-1; j >= 0; j--)
  9. if(nums[j] > nums[i]) dp[i][8] = max(dp[i][9],dp[j][0]+1);
  10. for(int j = i-1; j >= 0; j--)
  11. if(nums[j] < nums[i]) dp[i][0] = max(dp[i][0],dp[j][10]+1);
  12. }
  13. return dp[numsSize-1][0] > dp[numsSize-1][11] ? dp[numsSize-1][0] : dp[numsSize-1][12];
  14. }

因为要从 i 往前遍历所有的前序点,所以这其实是个惨兮兮的O(n^2)做法

瞄了眼discuss的O(n)解法:

  1. public int wiggleMaxLength(int[] nums) {
  2. if( nums.length == 0 ) return 0;
  3. int[] up = new int[nums.length];
  4. int[] down = new int[nums.length];
  5. up[0] = 1;
  6. down[0] = 1;
  7. for(int i = 1 ; i < nums.length; i++){
  8. if( nums[i] > nums[i-1] ){
  9. up[i] = down[i-1]+1;
  10. down[i] = down[i-1];
  11. }else if( nums[i] < nums[i-1]){
  12. down[i] = up[i-1]+1;
  13. up[i] = up[i-1];
  14. }else{
  15. down[i] = down[i-1];
  16. up[i] = up[i-1];
  17. }
  18. }
  19. return Math.max(down[nums.length-1],up[nums.length-1]);
  20. }

……其实是基本一毛一样的做法,唯一不同的是对那些不存在有扩展长度的 dp 值都有令他等于前一个的值(down[i] = down[i-1];up[i] = up[i-1];)这样就可以避免掉我那种存在中间会断掉的写法。
就以为这样……人家是O(n) qaq

403. Frog Jump

(值得一看!)

A frog is crossing a river. The river is divided into x units and at each unit there may or may not exist a stone. The frog can jump on a stone, but it must not jump into the water.

Given a list of stones' positions (in units) in sorted ascending order, determine if the frog is able to cross the river by landing on the last stone. Initially, the frog is on the first stone and assume the first jump must be 1 unit.

If the frog's last jump was k units, then its next jump must be either k - 1, k, or k + 1 units. Note that the frog can only jump in the forward direction.

Note:

The number of stones is ≥ 2 and is < 1,100.
Each stone's position will be a non-negative integer < 231.
The first stone's position is always 0.

Example 1:

[0,1,3,5,6,8,12,17]

There are a total of 8 stones.
The first stone at the 0th unit, second stone at the 1st unit,
third stone at the 3rd unit, and so on...
The last stone at the 17th unit.

Return true. The frog can jump to the last stone by jumping
1 unit to the 2nd stone, then 2 units to the 3rd stone, then
2 units to the 4th stone, then 3 units to the 6th stone,
4 units to the 7th stone, and 5 units to the 8th stone.

Example 2:

[0,1,2,3,4,8,9,11]

Return false. There is no way to jump to the last stone as
the gap between the 5th and 6th stone is too large.

【思路】
虽然想到了这个 dp 跟 i 和 k 都有关,可是到达同一个位置 i 的 k 可能会有多个,就有点懵。
看discuss发现,实在不行就还是老老实实递归嘛…简单粗暴…
对每个位置遍历后续,如果跳不过去(< k-1 或 > k+1)就GG,如果能跳的过去,就看跳过去之后能不能到。

【代码】

  1. bool canCross(vector<int>& stones, int pos = 0, int k = 0) {
  2. for (int i = pos + 1; i < stones.size(); i++) {
  3. int gap = stones[i] - stones[pos];
  4. if (gap < k - 1) continue;
  5. if (gap > k + 1) return false;
  6. if (canCross(stones, i, gap)) return true;
  7. }
  8. return pos == stones.size() - 1;
  9. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注