【leetcode_week136】困于环中的机器人_分隔数组以得到最大和等

这是第二次正儿八经参加leetcode的周赛,与上一次参加相比,没什么长进,依旧是一道AC,一道差一些。
看到了一个大神,关注了一下,以下所有的非参赛时间的代码全部参考大神,权作学习。



leetcode第136场周赛赛题地址: https://leetcode-cn.com/contest/weekly-contest-136


困于环中的机器人

在无限的平面上,机器人最初位于 (0, 0) 处,面朝北方。机器人可以接受下列三条指令之一:

“G”:直走 1 个单位 “L”:左转 90 度 “R”:右转 90 度 机器人按顺序执行指令 instructions,并一直重复它们。

只有在平面中存在环使得机器人永远无法离开时,返回 true。否则,返回 false。

示例 1:

输入:“GGLLGG”
输出:true
解释: 机器人从 (0,0) 移动到 (0,2),转 180 度,然后回到 (0,0)。
重复这些指令,机器人将保持在以原点为中心,2 为半径的环中进行移动。

思路和参赛代码

这题想了一下,有一个初步的未经证明的想法:机器人走一个循环,如果下次走的方向和这次循环开始的方向不同,那么最终会走成一个圈,方向相同(除去回到原点这一种情况)则能够继续往远处走,可以回来
本场周赛,几乎所有的时间都在整第三题,这个题最后才会过来做的,代码非常挫。。。。可以忽略直接看后面的

class Solution {
public:
    bool isRobotBounded(string instructions) {
        int start = 0, end = 0;
        int c[2] = {0, 0};
        
        switch(instructions[0]) {
            case 'G':
                start = 0;
                end = 0;
                c[0]++;
                break;
            case 'L':
                start = 1;
                end = 1;
                break;
            case 'R':
                start = 2;
                end = 2;
                break;
        }
        
        for (int i = 1; i < instructions.length(); i++) {
            switch(instructions[i]) {
            case 'G':
                switch(end) {
                    case 0:
                        c[0]++;
                        break;
                    case 1:
                        c[1]++;
                        break;
                    case 2:
                        c[0]--;
                        break;
                    case 3:
                        c[1]--;
                        break;
                }
                break;
            case 'L':
                switch(end) {
                    case 0:
                        end = 3;
                        break;
                    case 1:
                    case 2:
                    case 3:
                        end -= 1;
                        break;     
                }
                break;
            case 'R':
                switch(end) {
                    case 0:
                    case 1:
                    case 2:
                        end += 1;
                        break;
                    case 3:
                        end = 0;
                        break;     
                }
                break;
            }
        }
        
        switch(instructions[0]) {
            case 'G':
                break;
            case 'L':
                switch(end) {
                    case 0:
                        end = 3;
                        break;
                    case 1:
                    case 2:
                    case 3:
                        end -= 1;
                        break;     
                }
                break;
            case 'R':
                switch(end) {
                    case 0:
                    case 1:
                    case 2:
                        end += 1;
                        break;
                    case 3:
                        end = 0;
                        break;     
                }
                break;
            }
        
        if (c[0] == 0 && c[1] == 0) {
            return true; 
        }
        
        else if (end != start) {
            // 换了方向,会被困死
            return true;
        }
        else {
            return false;
        }
    }
};

别人代码

我自己的肯定还能精简非常多,当时时间不够写的匆忙。因为不是很难,所以也懒得想了。看了一下大神的代码

class Solution {
    int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
public:
    bool isRobotBounded(string instructions) {
        int x=0,y=0,z=0,i,n=instructions.size();
        for(i=0;i<n;i++)if(instructions[i]=='G')
        {
            x+=dx[z];
            y+=dy[z];
        }
        else if(instructions[i]=='L')z=z+3&3;
        else z=z+1&3;
        if(!x&&!y)return 1;
        return !!z;
    }
};

思路是一样的,也是看一轮动作,回到原点则是true,否则看方向是否与原来相同,这就简洁很多了。


不邻接植花

题目

有 N 个花园,按从 1 到 N 标记。在每个花园中,你打算种下四种花之一。

paths[i] = [x, y] 描述了花园 x 到花园 y 的双向路径。

另外,没有花园有 3 条以上的路径可以进入或者离开。

你需要为每个花园选择一种花,使得通过路径相连的任何两个花园中的花的种类互不相同。

以数组形式返回选择的方案作为答案 answer,其中 answer[i] 为在第 (i+1) 个花园中种植的花的种类。花的种类用 1,2, 3, 4 表示。保证存在答案。

示例 1:

输入:N = 3, paths = [[1,2],[2,3],[3,1]]
输出:[1,2,3]

别人的解答

这题一开始看,感觉像图着色问题,图方面的暂时没有弄的打算,慢慢来,所以这题略过了。后来看了一下,发现好像可以回溯来做。 由于还有别的事情,也没有在结束后再来做这道题,直接上别人的代码吧

class Solution {
public:
    vector<int> gardenNoAdj(int N, vector<vector<int>>& paths) {
        vector<int> v[N];
        for (auto e : paths)
        {
            v[e[0]-1].push_back(e[1]-1);
            v[e[1]-1].push_back(e[0]-1);
        }
        vector<int> u(N);
        for (int i = 0; i < N; ++ i)
        {
            if (u[i]) continue;
            queue<int> Q;
            Q.push(i);
            u[i] = 1;
            while (!Q.empty())
            {
                int x = Q.front();
                Q.pop();
                for (auto y : v[x])
                {
                    if (u[y]) continue;
                    for (int c = 1; c <= 4; ++ c)
                    {
                        int flag = 0;
                        for (auto z : v[y])
                            if (u[z] == c) flag = 1;
                        if (!flag)
                        {
                            u[y] = c;
                            break;
                        }
                    }
                    Q.push(y);
                }
            }
        }
        return u;
    }
};

分隔数组以得到最大和

题目

给出整数数组 A,将该数组分隔为长度最多为 K 的几个(连续)子数组。分隔完成后,每个子数组的中的值都会变为该子数组中的最大值。
返回给定数组完成分隔后的最大和。

示例:

输入:A = [1,15,7,9,2,5,10], K = 3
输出:84
解释:A 变为 [15,15,15,9,10,10,10]

提示:

1 <= K <= A.length <= 500
0 <= A[i] <= 10^6

思路和代码

这道题看上去是可以动态规划解的,我之前也是想好好补动态规划,所以几乎所有的时间都花在这上面了,但最后还是超时了。贴一下我的代码

class Solution {
public:
    int dp[500][500];
    
    int maxsum(int i, int j, int K, vector<int>& A) {
        if (dp[i][j] != -1) {
            return dp[i][j];
        }
        else if (i == j) {
            dp[i][j] = A[i];
            return dp[i][j];
        }
        else if(j - i + 1 <= K) {
            int tmpmax = -1;
            for (int m = i; m <= j; m++) {
                tmpmax = max(tmpmax, A[m]);
            }
            dp[i][j] = tmpmax * (j-i+1);
            
            return dp[i][j];
        }
        else {
            int tmpmax = -1;
            for (int m = 0; m < K, i+m+1<=j; m++) {
                tmpmax = max(tmpmax, maxsum(i, i+m, K, A)+maxsum(i+m+1, j, K, A));
            }
            dp[i][j] = tmpmax;
            return dp[i][j];
        }
    }
    
    int maxSumAfterPartitioning(vector<int>& A, int K) {
        
        memset(dp, -1, sizeof(dp));
        return maxsum(0, A.size()-1, K, A);
        
    }
};

再贴一下别人的代码

class Solution {
public:
    int maxSumAfterPartitioning(vector<int>& A, int K) {
        int m[505][505],n=A.size(),i,j,f[505];
        for(i=0;i<n;i++)for(m[i+1][i+1]=A[i],j=i+1;j<n;j++)m[i+1][j+1]=max(m[i+1][j],A[j]);
        memset(f,0,sizeof(f));
        for(i=1;i<=n;i++)for(j=1;j<=i&&j<=K;j++)f[i]=max(f[i],f[i-j]+m[i-j+1][i]*j);
        return f[n];
    }
};

天壤之别,大写的


最长重复子串

这题也没有看,直接上别人的解答:
https://leetcode-cn.com/discuss/forum.php?mod=viewthread&tid=906
以及 大神的代码:

class Solution {
public:
    typedef long long ll;
    int P=998244353,P1=1000000007,base=233,base1=666;
    int h[100005],h1[100005],p[100005],p1[100005];
    set<pair<int,int>> s;
    string longestDupSubstring(string S) {
        int n=S.size(),i,j,k,l,r,mid;
        pair<int,int> o;
        for(i=h[0]=0;i<n;i++)h[i+1]=((ll)h[i]*base+S[i])%P;
        for(i=h1[0]=0;i<n;i++)h1[i+1]=((ll)h1[i]*base1+S[i])%P1;
        for(i=p[0]=1;i<=n;i++)p[i]=(ll)p[i-1]*base%P;
        for(i=p1[0]=1;i<=n;i++)p1[i]=(ll)p1[i-1]*base1%P1;
        l=0;
        r=n;
        while(l+1<r)
        {
            mid=l+r>>1;
            s.clear();
            for(i=mid;i<=n;i++)
            {
                j=(h[i]+(ll)(P-h[i-mid])*p[mid])%P;
                k=(h1[i]+(ll)(P1-h1[i-mid])*p1[mid])%P1;
                o=make_pair(j,k);
                if(s.find(o)==s.end())s.insert(o);
                else break;
            }
            if(i>n)r=mid;
            else l=mid;
        }
        s.clear();
        for(i=l;i<=n;i++)
        {
            j=(h[i]+(ll)(P-h[i-l])*p[l])%P;
            k=(h1[i]+(ll)(P1-h1[i-l])*p1[l])%P1;
            o=make_pair(j,k);
            if(s.find(o)==s.end())s.insert(o);
            else break;
        }
        string ans="";
        for(j=i-l;j<i;j++)ans+=S[j];
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值