第一次參加周賽,只會答出來最簡單的一題,第二題超時,第三、四題不會做,這裏來總結一下,並希望下次有進步。
第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庫運用還不夠熟練。
畢竟才刷了幾十道簡單的題,不可能一下子進步很多,不過肉眼可見的確在進步中。
希望自己改進的點就是,要堅持每題都做總結,慢慢來,比較快。