LeetCodeWeeklyContest-181

Rank:1121 / 4148 AC 2/4

题目传送

5364. 按既定顺序创建目标数组

签到题
当时手写的数组后移,其实可以用vector的insert…

class Solution {
public:
    vector<int> createTargetArray(vector<int>& nums, vector<int>& index) {
        int n = index.size();
        vector<int> target(n,-1);
        for(int i=0;i<n;i++){
            if(target[index[i]]!=-1){
                for(int j=n-1;j>index[i];j--){
                    if(j>0)target[j] = target[j-1];
                }
                target[index[i]] = nums[i];
            }
            else target[index[i]] = nums[i];
        }
        return target;

    }
};

insert 版本

class Solution {
public:
    vector<int> createTargetArray(vector<int>& nums, vector<int>& index) {
        int n = index.size();
        vector<int> target;
        for(int i=0;i<n;i++){
            target.insert(target.begin()+index[i],nums[i]);
        }
        return target;
    }
};

平均时间复杂度 O ( n 2 ) O(n^2) O(n2)

5178. 四因数

这里有个唯一分解定理,大概是任意一个数x都可以被分解成素数的乘积
x = p 1 a 1 ∗ p 2 a 2 ∗ p 3 a 3 ∗ p 4 a 4 ∗ . . . . . p s a s x = p_1^{a_1}*p_2^{a_2}*p_3^{a_3}*p_4^{a_4}*.....p_s^{a_s} x=p1a1p2a2p3a3p4a4.....psas
因子的个数:
∏ j = 1 s ( a j + 1 ) \prod_{j=1}^s (a_j+1) j=1s(aj+1)
因子的和:
∏ j = 1 s p j a j + 1 − 1 p j − 1 \prod_{j=1}^s \frac {p_j^{a_j+1}-1}{p_j-1} j=1spj1pjaj+11

class Solution {
public:
    int fun(int n,long long &sum){
        long long s = 1;
        sum = 1;
        for(int i=2;i*i<=n;i++){
            int cnt = 0,a=1;
            while(n%i==0){
                n /= i;
                a *= i;
                cnt++;
            }
            s = s*(cnt+1);
            sum = sum*(a*i-1)/(i-1);
        }
        if(n>1) {
            s = s*2;sum = sum*(n+1);
        }
        if(s!=4) sum = 0;
        return s; 
    }
    int sumFourDivisors(vector<int>& nums) {
        long long sum = 0;
        long long s= 0;
        for(int i=0;i<nums.size();i++){
            fun(nums[i],s);
            sum += s;
        }
        return sum;
    }
};

时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)

5366. 检查网格中是否存在有效路径

题目稍微变化一下,就不会写了…
参考:建图+dfs 40 行左右

大题思路是: 把原来每个方格,再变成3*3的小格子,然后在去标记,就类似走迷宫。

class Solution {
public:
    int maps[1000][1000];
    int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1},m,n;
    void fill(int i,int j,int s){
        maps[i+1][j+1] =1;
        if(s==1) maps[i+1][j]=maps[i+1][j+2] =1;
        else if(s==2) maps[i][j+1] = maps[i+2][j+1] =1;
        else if(s==3) maps[i+1][j] = maps[i+2][j+1] = 1;
        else if(s==4) maps[i+2][j+1] = maps[i+1][j+2] = 1;
        else if(s==5) maps[i+1][j] = maps[i][j+1] = 1;
        else if(s==6) maps[i][j+1] = maps[i+1][j+2] = 1;
    }
    void dfs(int i,int j){
        maps[i][j] = 0;
        for(int k=0;k<4;k++){
            int x = i+dx[k],y = j+dy[k];
            if(x>=0&&x<3*m&&y>=0&&y<3*n&&maps[x][y])
                dfs(x,y);
        }
    }
    bool hasValidPath(vector<vector<int>>& g) {
        m = g.size(),n = g[0].size();
        memset(maps,0,sizeof(maps));
        for(int i=0;i<3*m;i+=3){
            for(int j=0;j<3*n;j+=3){
                fill(i,j,g[i/3][j/3]);
            }
        }
        dfs(1,1);
        return maps[3*m-2][3*n-2] == 0;
    }
};

时间复杂度 O ( m ∗ n ) O(m*n) O(mn)

5367. 最长快乐前缀

题目让求的是最长的既是前缀也是后缀的字符串。
其实直接暴力求解,对比子串的话,会爆内存。

最长的既是前缀也是后缀的字符串,其实kmp算法的next数组就是记录了这个字符串的长度,next[j]代表 [0, j - 1] 区段中最长相同真前后缀的长度,这里提到了真前缀,真后缀,区别于前缀、后缀,就是不包括原字符串本身。所以next[len]就记录了原字符串的最长相同的真前后缀的长度,其实len为原字符串的长度。

class Solution {
public:
    string longestPrefix(string s) {
        int next[100010];
        int k=-1,i=0,len = s.length();
        next[0] = -1;
        while(i<len){
            if(k==-1||s[i]==s[k]){
                k++;i++;
                next[i] = k;
            }
            else k = next[k];
        }
        if(next[len]==0) return "";
        return s.substr(0,next[len]);
    }
};

时间复杂度 O ( n ) O(n) O(n)
Hash解法
整体的思路是 如果两个字符串的hash相同,则可以认为两个字符串是相同的
参考《算法进阶指南》字符串hash章节
建议使用模数为 2 64 2^{64} 264,这样的话,直接使用 unsigned long long 即可,还能避免取模运算,这样会自动截断或取模。
常用位权p,有131,13331,书上说这样的Hash算法很难产生冲突。
H a s h ( T ) = H a s h ( S + T ) − H a s h ( S ) ∗ P l e n g t h ( T ) Hash(T) = Hash(S+T)-Hash(S)*P^{length(T)} Hash(T)=Hash(S+T)Hash(S)Plength(T)
其中S、T均为字符串。

typedef unsigned long long ull; 
const int maxn = 1e5+10;
class Solution {
public:
    string longestPrefix(string s) {
        int p = 131,len = s.length(),res=0;
        ull H[maxn],w[maxn]; 
        H[0] = 0;w[0] = 1;
        for(int i=1;i<=len;i++){
            H[i] = H[i-1]*p+s[i-1]-'a'+1;
            w[i] = w[i-1]*p;
        }
        for(int i=1;i<len;i++){
            ull pre = H[i];
            // ull post = H[len]-H[len-i]*(ull)pow(p,i); //如果使用pow绩点要用ull强转一下
            ull post = H[len]-H[len-i]*w[i];
            if(pre==post) res = i;
        }
        return s.substr(0,res);
    }
};

时间复杂度 O ( n ) O(n) O(n)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值