算法设计与结构基础作业第十二周

55.Jump Game

Description:

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.

分析:

一开始想到最naïve 的方法,按照题意,一个个标记所有能到达的点,最后看终点是否可达。这个算法时间复杂度最坏情况O(n*n), 空间复杂度O(n),最后超时。然后改为正向的深度优先搜索,向下继续搜索时也是自小到大,发现会有很多重叠的子问题,加入记忆化,还是超时,结合贪心策略改为自大向小结果一样;然后改为反向的深度优先搜索,从终点往起点求解,加入记忆化,最终通过,这一种方法经过分析应该是O(n)的,最后回到正向搜索发现剪枝剪得不好,修改后应该同样是O(n)的复杂度,原本最差应该是O(n*n)。最后看别人的解法发现每个点携带的信息只有最大值有用,最naïve的方法花费了大量工作处理无用信息。

My C++ code:


class Solution {
public:
    bool canJump(vector<int>& nums) {
        vector<bool> m(nums.size(), true);
        return dfs(0, nums, m);
    }
    
    bool dfs(int start, vector<int> &nums, vector<bool> &m)
    {
        if(start == nums.size()-1)
        {
            return true;
        }
        bool res = false;
        for(int i = nums[start]; i >= 1; --i)
        {
            if(i + start >= nums.size())
                continue;
            if(!m[start+i])
                break;
            res = m[start+i] = dfs(i+start, nums, m);
            if(res)
                return true;
        }
        return res;
    }
};


134.Gas Station
Description"
There are N gas stations along a circular route, where the amount of gas at station i is gas[i].

You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations.

Return the starting gas station's index if you can travel around the circuit once, otherwise return -1.

Note:
The solution is guaranteed to be unique.

分析:

最开始没什么想法,如果每个点深度优先一次将是O(n)的复杂度,另外只是猜测如果油量总和大于消耗总和一定存在解。然后想到一个类似KMP不做回溯的解法,最多相当于遍历两趟序列,O(n),算法结束的条件是找到解或者起点回到0,然后实现这个算法通过。最后看别人的解法,有一个要点是如果不能跨过某个油站,新的起点一定在其后,这个没想到的点很关键,实现的算法也很简洁,另外就是解一定存在的证明。

My C++ code:

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int start = 0, end = 0, gas_balance = 0, path_length = 0;
        while(true)
        {
            if(start >= gas.size())
            {
                return -1;
            }
            if(path_length == gas.size())
            {
                return start;
            }
            if(gas_balance + gas[end] < cost[end])
            {
                while(start < gas.size() && gas_balance + gas[end] < cost[end])
                {
                    if(start == end)
                    {
                        start = ++end;
                        if(start >= gas.size())
                        {
                            return -1;
                        }
                        gas_balance = 0;
                        path_length = 0;
                    }
                    else
                    {
                        gas_balance += cost[start] - gas[start];
                        start++;
                        --path_length;
                    }
                }
                if(start >= gas.size())
                {
                    return -1;
                }
            }
            else
            {
                gas_balance += gas[end] - cost[end];
                ++end;
                ++path_length;
                if(end >= gas.size())
                {
                    end = end % gas.size();
                }
            }
        }
    }
};





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值