學習筆記 | Leetcode 181周賽

在這裏插入圖片描述第一次參加周賽,只會答出來最簡單的一題,第二題超時,第三、四題不會做,這裏來總結一下,並希望下次有進步。
第181場leetcode 周賽

5364. 按既定順序創建目標數組

給你兩個整數數組 nums 和 index。你需要按照以下規則創建目標數組:

  • 目標數組 target 最初爲空。
  • 按從左到右的順序依次讀取 nums[i] 和 index[i],在 target 數組中的下標 index[i] 處插入值 nums[i] 。
  • 重複上一步,直到在 nums 和 index 中都沒有要讀取的元素。

請你返回目標數組。

思路:題目比較簡單,直接暴力求解即可

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

5178. 四因數

給你一個整數數組 nums,請你返回該數組中恰有四個因數的這些整數的各因數之和。

如果數組中不存在滿足題意的整數,則返回 0 。

示例:

輸入:nums = [21,4,7]
輸出:32
解釋: 21 有 4 個因數:1, 3, 7, 21
4 有 3 個因數:1, 2, 4
7 有 2 個因數:1, 7
答案僅爲 21 的所有因數的和。

提示:
1 <= nums.length <= 10^4
1 <= nums[i] <= 10^5

未通過的思路:
第一反應就是暴力求解啊,隱約覺得可能超時,果不其然超時了,而且我考慮的也不周全,沒有考慮到立方根的問題

看過大佬們的思路:4個因子的話,可以分爲1和本身+剩下兩個因子,這兩個因子可以是質數相乘,但是如果是個立方根的話,就得捨去了。

#include <math.h>

class Solution {
public:
    int sumFourDivisors(vector<int>& nums) {
        int res = 0;
        
        for(int i = 0; i < nums.size(); ++i){
            int cnt = 0;
            int sum = 0;
            int sq = sqrt(nums[i]);

            for(int j = 2; j <= sq; ++j){
                if(nums[i] % j == 0){
                    cnt++;
                    sum += j;
                    sum += nums[i] / j;
                    
                }
                if(cnt > 1) break;
            }
            if(cnt == 1 && sq * sq != nums[i]){
                res = res + sum + nums[i] + 1;
            } 
        }
        
        return res;
    }
};



1391. 檢查網格中是否存在有效路徑
給你一個 m x n 的網格 grid。網格里的每個單元都代表一條街道。grid[i][j] 的街道可以是:

1 表示連接左單元格和右單元格的街道。
2 表示連接上單元格和下單元格的街道。
3 表示連接左單元格和下單元格的街道。
4 表示連接右單元格和下單元格的街道。
5 表示連接左單元格和上單元格的街道。
6 表示連接右單元格和上單元格的街道。

你最開始從左上角的單元格 (0,0) 開始出發,網格中的「有效路徑」是指從左上方的單元格 (0,0) 開始、一直到右下方的 (m-1,n-1) 結束的路徑。該路徑必須只沿着街道走。

注意:你不能變更街道。

如果網格中存在有效的路徑,則返回 true,否則返回 false 。

思路:這題其實襲擊想的時候直到只要轉換好就可以,但是無奈題刷得少,不知道咋轉換,於是看了別的大佬的題解:鏈接

pipe[3][2]=3,代表3號拼圖可以由向上的方向進入其中,並轉向左方向繼續前進。
pipe[5][3]=-1,代表5號拼圖不可以由向左的方向進入其中。

class Solution {
    int m,n,dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};//0下、1右、2上、3左
    int pipe[7][4]={
        {-1,-1,-1,-1},
        {-1,1,-1,3},
        {0,-1,2,-1},
        {-1,0,3,-1},
        {-1,-1,1,0},
        {3,2,-1,-1},
        {1,-1,-1,2}
    };
    //記錄各個拼圖塊路徑的方向,0、1、2、3代表方向,-1代表不可走。
    bool vis[302][302];
    bool dfs(int x,int y,int dir,vector<vector<int>>& grid){//(x,y,當前方向,地圖)
        vis[x][y]=1;
        if(x==m-1&&y==n-1) return 1;//到達終點
        int xx=x+dx[dir];
        int yy=y+dy[dir];//得到下一個準備走的座標
        if(xx<0||yy<0||xx>=m||yy>=n)return 0;//越界
        int nxt=grid[xx][yy];//得到下一塊拼圖的編號
        if(pipe[nxt][dir]!=-1&&!vis[xx][yy])
            return dfs(xx,yy,pipe[nxt][dir],grid);//如果當前方向可走,則方向改變,繼續走。
        return 0;//無法走,返回0
    }
    public:
    bool hasValidPath(vector<vector<int>>& grid) {    
        m=grid.size();
        n=grid[0].size();
        memset(vis,0,sizeof(vis));
        int sta=grid[0][0];//起點的拼圖編號
        for(int i=0;i<4;++i)//朝着四個方向都試一下
            if(pipe[sta][i]!=-1)//當前方向可以走
                if(dfs(0,0,pipe[sta][i],grid))//沿着當前方向搜索
                    return 1;//拼圖都有兩個方向可以走,只要沿着一個初始方向走通就可以。
        return 0;
    }
};

1392. 最長快樂前綴*
(這題還不是太懂,等我把簡單+中等難度題刷的差不多了再回過頭來看可能那時候就懂了。)

「快樂前綴」是在原字符串中既是 非空 前綴也是後綴(不包括原字符串自身)的字符串。 給你一個字符串 s,請你返回它的 最長快樂前綴。
如果不存在滿足題意的前綴,則返回一個空字符串。

方法一:KMP算法

class Solution {
public:
    string longestPrefix(string s) {
        int n = s.size();
        vector<int> fail(n, -1);
        for (int i = 1; i < n; ++i) {
            int j = fail[i - 1];
            while (j != -1 && s[j + 1] != s[i]) {
                j = fail[j];
            }
            if (s[j + 1] == s[i]) {
                fail[i] = j + 1;
            }
        }
        return s.substr(0, fail[n - 1] + 1);
    }
};

來源:官方題解二

方法二:字符串Hash

typedef unsigned long long ULL;
class Solution {
public:
    string longestPrefix(string s) {
        int base = 131;
        ULL p[100002]; 
        p[0] = 1;
        ULL hash[100002]; 
        hash[0] = 0;
        for (int i = 1; i <= s.size(); i ++) {
            hash[i] = hash[i-1] * base + s[i-1] - 'a' + 1;
            p[i] = p[i-1] * base;
        }
        for (int i = s.size() - 1; i >= 1; i --) {
            ULL pre = hash[i];
            ULL suf = hash[s.size()] - hash[s.size()-i] * p[i];
            if (pre == suf) {
                return s.substr(0, i);
            }
        }
        return "";
    }
};

來源:huwt


總結與反思
這週考的算法主要是DFS和KMP算法,我主要是STL庫運用還不夠熟練。
畢竟才刷了幾十道簡單的題,不可能一下子進步很多,不過肉眼可見的確在進步中。
希望自己改進的點就是,要堅持每題都做總結,慢慢來,比較快。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章