LeetCode_Jump Game&&Jump Game II

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Determine if you are able to reach the last index.

For example:
A = [2,3,1,1,4], return true.

A = [3,2,1,0,4], return false.

对于题目一,思路很简单,贪心,只需要时刻计算前位置和当前位置所能跳的最远长度,并始终和n作比较就可以:

1,若在任意pos位置出现maxstep为0的情况,则说明无法继续向前移动,返回false

2.若在任意pos位置出现maxstep+pos>=n说明可以完成最后一跳,返回true

代码如下:

class Solution {
public:
    bool canJump(int A[], int n) {
        if(n==0||n==1){
            return true;
        }
        int maxstep=A[0];
        for(int i=1;i<n;i++){
            if(maxstep==0) return false;
            maxstep--;
            if(maxstep<A[i]){
                maxstep=A[i];
            }
            if(maxstep+i>=n-1){
                return true;
            }
        }
    }
};

第二道题是在第一题的追问,要求给出最小跳数,我的最初想法就是BFS(因为题目要求最小么,呵呵),下面是我的BFS的MLE代码:

struct curinfo{
	int pos;
	int jumpNo;
	int maxStep;
	curinfo (int p,int j,int m):pos(p),jumpNo(j),maxStep(m){};
	curinfo (const curinfo &c):pos(c.pos),jumpNo(c.jumpNo),maxStep(c.maxStep){};
	curinfo & operator= (const curinfo &c){
		if(this!=&c){
			pos=c.pos;
			jumpNo=c.jumpNo;
			maxStep=c.jumpNo;
		}
		return *this;
	};
};

class Solution{
public:
	int jump(int A[],int n){
		if(n<=1) return 0;

		curinfo cs(0,0,A[0]);
		queue <curinfo> bfsQueue;
		bfsQueue.push(cs);

		while(!bfsQueue.empty()){
			cs=bfsQueue.front();
			bfsQueue.pop();

			for(int i=1;i<=cs.maxStep;i++){
				if(cs.pos+i>=n-1) return cs.jumpNo+1;
				else{
					bfsQueue.push(cs.pos+i,jumpNo+1,A[cs.pos+i]);
				}
			}
		}
		return -1;
	}
};

于是在Discuss中看到别人的代码仍然使用贪心,只不过是要记录当前一跳所能到达的最远距离、上一跳所能达到的最远距离,和当前所使用跳数就可以了代码如下:

/*
 * We use "last" to keep track of the maximum distance that has been reached
 * by using the minimum steps "ret", whereas "curr" is the maximum distance
 * that can be reached by using "ret+1" steps. Thus,
 * curr = max(i+A[i]) where 0 <= i <= last.
 */
class Solution {
public:
    int jump(int A[], int n) {
        int ret = 0;//当前跳数
        int last = 0;//上一跳可达最远距离
        int curr = 0;//当前一跳可达最远距
        for (int i = 0; i < n; ++i) {
            //无法向前继跳直接返回
            if(i>curr){
                return -1;
            }
            //需要进行下次跳跃,则更新last和当执行的跳数ret
            if (i > last) {
                last = curr;
                ++ret;
            }
            //记录当前可达的最远点
            curr = max(curr, i+A[i]);
        }

        return ret;
    }
};



  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目描述: 给定一个字符串,请将字符串里的字符按照出现的频率降序排列。 示例 1: 输入: "tree" 输出: "eert" 解释: 'e'出现两次,'r'和't'都只出现一次。因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。 示例 2: 输入: "cccaaa" 输出: "cccaaa" 解释: 'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。注意"cacaca"是不正确的,因为相同的字母必须放在一起。 示例 3: 输入: "Aabb" 输出: "bbAa" 解释: 此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。注意'A'和'a'被认为是两种不同的字符。 Java代码如下: ``` import java.util.*; public class Solution { public String frequencySort(String s) { if (s == null || s.length() == 0) { return ""; } Map<Character, Integer> map = new HashMap<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); map.put(c, map.getOrDefault(c, 0) + 1); } List<Map.Entry<Character, Integer>> list = new ArrayList<>(map.entrySet()); Collections.sort(list, (o1, o2) -> o2.getValue() - o1.getValue()); StringBuilder sb = new StringBuilder(); for (Map.Entry<Character, Integer> entry : list) { char c = entry.getKey(); int count = entry.getValue(); for (int i = 0; i < count; i++) { sb.append(c); } } return sb.toString(); } } ``` 解题思路: 首先遍历字符串,使用HashMap记录每个字符出现的次数。然后将HashMap转换为List,并按照出现次数从大到小进行排序。最后遍历排序后的List,将每个字符按照出现次数依次添加到StringBuilder中,并返回StringBuilder的字符串形式。 时间复杂度:O(nlogn),其中n为字符串s的长度。遍历字符串的时间复杂度为O(n),HashMap和List的操作时间复杂度均为O(n),排序时间复杂度为O(nlogn),StringBuilder操作时间复杂度为O(n)。因此总时间复杂度为O(nlogn)。 空间复杂度:O(n),其中n为字符串s的长度。HashMap和List的空间复杂度均为O(n),StringBuilder的空间复杂度也为O(n)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值