Leetcode 1306. 跳跃游戏 III

2019年的最后一天了,善始善终,上次报名的第169场Leetcode竞赛忘记参加了,那天上午干啥了???

然后补做了一下那个题目,还是挺简单的,下面做一下笔记和解题思路。


 第一题:

  1304. 和为零的N个唯一整数

   给你一个整数 n,请你返回 任意 一个由 n 个 各不相同 的整数组成的数组,并且这 n 个数相加和为 0 。

    示例 1:

  输入:n = 5
  输出:[-7,-1,1,3,4]
  解释:这些数组也是正确的 [-5,-1,1,2,3],[-3,-1,2,-2,4]。

思路:
 
 由于(+x)+(-x)和为0,即互为相反数的两个值相加即可
  给定的n值有奇数偶数之分,是否包含元素0,如果奇数,则需要包含0,偶数去掉0,即可。
代码如下: 
 1 class Solution {
 2 public:
 3     vector<int> sumZero(int n) {
 4         vector<int> res;
 5         //从-n/2 到 n/2 依次存入结果集即可
 6         for(int i=-n/2;i<=n/2;i++)
 7         {
 8             if(i==0 && n%2==0)
 9                 continue;
10             res.push_back(i);
11         }
12         return res;
13     }
14 };

第二题:

  1305. 两棵二叉搜索树中的所有元素

  给你 root1 和 root2 这两棵二叉搜索树。

  请你返回一个列表,其中包含 两棵树 中的所有整数并按 升序 排序。.

  

思路:

  最简单最直接的方法,即将两棵树进行遍历,存入一个vector中,然后排序即可,(这里我们使用先序遍历方法)

代码如下:

 1 /**
 2  * Definition for a binary tree node.
 3  * struct TreeNode {
 4  *     int val;
 5  *     TreeNode *left;
 6  *     TreeNode *right;
 7  *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 8  * };
 9  */
10 class Solution {
11 public:
12     vector<int> getAllElements(TreeNode* root1, TreeNode* root2) {
13         vector<int> res;
14         //遍历两棵树,节点存入res中去
15         dfs(root1,res);
16         dfs(root2,res);
17         sort(res.begin(),res.end());
18         return res;
19     }
20 
21     void dfs(TreeNode* root,vector<int> &res)
22     {
23         //先序遍历
24         if(root==nullptr)
25             return;
26         res.push_back(root->val);
27         dfs(root->left,res);
28         dfs(root->right,res);
29     }
30 };

 第三题:

   1306. 跳跃游戏 III

  这里有一个非负整数数组 arr,你最开始位于该数组的起始下标 start 处。当你位于下标 i 处时,你可以跳到 i + arr[i] 或者 i - arr[i]。

  请你判断自己是否能够跳到对应元素值为 0 的 任意 下标处。

  注意,不管是什么情况下,你都无法跳到数组之外。 

  示例 1:

  输入:arr = [4,2,3,0,3,1,2], start = 5  
  输出:true
  解释:
    到达值为 0 的下标 3 有以下可能方案:
    下标 5 -> 下标 4 -> 下标 1 -> 下标 3
    下标 5 -> 下标 6 -> 下标 4 -> 下标 1 -> 下标 3

思路:

  我们假设从start位置开始出发,有两条路可以走,要么左,要么右,所走的步长是arr[start],下一步的位置为start+arr[start]或者start-arr[start],对于新的位置有如下几种情况:

  1. 向右走超过了数组的最大范围

  2. 向左走超多了数组的最小范围

  3. 访问了已经访问过的位置,即从第一次访该位置,走了一圈又回到了原点(这点儿很重要,避免死循环)

  对于以上情况,我们将终止行走,认为此路不通。

  经过分析,好像题目类似于二叉树的搜索,搜索一条路径,使得终止节点上的数为0,首先想到的是用栈来模拟回溯操作,但这样频繁的出栈和入栈,干脆递归好了~~~

  除了以上几种情况,我们将对该start结点的值进行访问,看是否为0,然后以start - arr[start] start - arr[start] 为新的开始结点,进行递归操作。

  申请一个vector<int> flag,用来记录该位置是否被访问过~

  代码如下:

 1 class Solution {
 2 public:
 3     bool canReach(vector<int>& arr, int start) {
 4         //类似于树的遍历,递归实现,start认为是根节点
 5         vector<int> flag;
 6         flag.resize(arr.size(),0);
 7         dfs(arr,start,flag);
 8         return res;
 9     }
10 
11     void dfs(vector<int> arr,int pos,vector<int>& flag){
12         //先序遍历
13         if(pos<0 || pos>=arr.size() || flag[pos]==1)
14             return;
15         if(arr[pos]==0)
16         {
17             res=true;
18             return;
19         }
20         flag[pos]=1;  //置为已被访问
21         dfs(arr,pos-arr[pos],flag);
22         dfs(arr,pos+arr[pos],flag);
23     }
24     bool res=false;
25 };

看结果,这。。。也太刺激了吧~~~(●´∀`●)

 最后一题还没做~

posted @ 2019-12-31 10:27  _小学生  阅读(270)  评论(0编辑  收藏  举报