ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

labuladong的一些刷题记录

2021-12-28 23:05:27  阅读:177  来源: 互联网

标签:return 记录 int ++ vector grid ans labuladong 刷题


labuladong

岛屿问题

200. 岛屿数量

  • 思路+解法:

    1. DFS O(mn)

      class Solution {
      public:
          int nr, nc;
          void dfs(vector<vector<char>>& g, int r, int c){
              if(!(r >= 0 && r < nr)) return;
              if(!(c >= 0 && c < nc)) return;
              if(g[r][c] == '0') return;
      
              g[r][c] = '0';
              dfs(g, r + 1, c);
              dfs(g, r - 1, c);
              dfs(g, r, c + 1);
              dfs(g, r, c - 1);
          }
          int numIslands(vector<vector<char>>& grid) {
              int ans = 0;
              nr = grid.size();
              nc = grid[0].size();
              for(int i = 0; i < nr; i++){
                  for(int j = 0; j < nc; j++){
                      if(grid[i][j] == '1'){
                          ans++;
                          dfs(grid, i, j);
                      }
                  }
              }
              return ans;
          }
      };
      
    2. BFS O(mn)

      class Solution {
      public:
          int numIslands(vector<vector<char>>& grid) {
              int ans = 0;
              int nr = grid.size();
              int nc = grid[0].size();
              queue<pair<int,int>> q;
              for(int i = 0; i < nr; i++){
                  for(int j = 0; j < nc; j++){
                      if(grid[i][j] == '1'){
                          ans++;
                          q.push({i, j});
                          while(!q.empty()){
                              pair<int, int> loc = q.front();
                              q.pop();
                              int x = loc.first, y = loc.second;
                              if(x >= 1 && grid[x - 1][y] == '1'){
                                  q.push({x - 1, y});
                                  grid[x - 1][y] = '0';
                              }
                              if(x < nr - 1 && grid[x + 1][y] == '1'){
                                  q.push({x + 1, y});
                                  grid[x + 1][y] = '0';
                              }
                              if(y >= 1 && grid[x][y - 1] == '1'){
                                  q.push({x, y - 1});
                                  grid[x][y - 1] = '0';
                              }
                              if(y < nc - 1 && grid[x][y + 1] == '1'){
                                  q.push({x, y + 1});
                                  grid[x][y + 1] = '0';
                              }
                          }
                      }
                  }
              }
              return ans;
          }
      };
      
    3. 并查集 O(mn**α*(mn))

      class Solution {
      public:
          int nr, nc;
          int cnt;
          vector<int> par;
          int find(int x){
              if(par[x] == x) return x;
              return par[x] = find(par[x]);
          }
          //关键
          void unite(int a, int b){
              if(find(a) == find(b)) return;
              par[find(b)] = find(a);
              cnt--;
          }
          int numIslands(vector<vector<char>>& grid) {
              vector<vector<char>> copy_grid = grid;
              nr = grid.size();
              nc = grid[0].size();
              for(int i = 0; i < nr; i++){
                  for(int j = 0; j < nc; j++){
                      par.push_back(i * nc + j);
                  }
              }
              cnt = nr * nc;
              for(int i = 0; i < nr; i++){
                  for(int j = 0; j < nc; j++){
                      if(grid[i][j] == '1'){
                          if(i > 0 && grid[i - 1][j] == '1') unite(i * nc + j, (i - 1) * nc  + j);
                          if(i < nr - 1 && grid[i + 1][j] == '1') unite(i * nc + j, (i + 1) * nc + j);
                          if(j > 0 && grid[i][j - 1] == '1') unite(i * nc + j, i * nc + (j - 1));
                          if(j < nc - 1 && grid[i][j + 1] == '1') unite(i * nc + j, i * nc + (j + 1));
                          grid[i][j] = '0';
                      }
                      else cnt--;
                  }
              }
              return cnt;
          }
      }
      

1254. 统计封闭岛屿的数目

  • 思路+解法:

    1. DFS O(mn) 把靠边的岛屿先都淹了

      class Solution {
      public:
          //把靠边的岛屿淹了
          int nr, nc;
          void dfs(vector<vector<int>>& g, int r, int c){
              if(r < 0 || r >= nr || c < 0 || c >= nc) return;
              if(g[r][c] == 1) return;
      
              g[r][c] = 1;
              dfs(g, r + 1, c);
              dfs(g, r - 1, c);
              dfs(g, r, c + 1);
              dfs(g, r, c - 1);
          }
          int closedIsland(vector<vector<int>>& grid) {
              nr = grid.size(), nc = grid[0].size();
              for(int i = 0; i < nr; ++i){
                  dfs(grid, i, 0);
                  dfs(grid, i, nc - 1);
              }
              for(int j = 0; j < nc; ++j){
                  dfs(grid, 0, j);
                  dfs(grid, nr - 1, j);
              }
              int ans = 0;
              for(int i = 1; i < nr; ++i){
                  for(int j = 1; j < nc; ++j){
                      if(grid[i][j] == 0){
                          ans++;
                          dfs(grid, i, j);
                      }
                  }
              }
              return ans;
          }
      };
      

1020. 飞地的数量

  • 思路+解法:

    1. 对于每个点dfs找出口 超时

      class Solution {
      public:
          int nr;
          int nc;
          vector<vector<int>> dir = {{1, 0},{-1, 0},{0, 1},{0, -1}};
          vector<vector<bool>> vis;
          bool dfs(vector<vector<int>>& g, int r, int c){
              if(r < 0 || r >= nr || c < 0 || c >= nc) return true;
              if(vis[r][c]) return false;
              if(g[r][c] == 0) return false;
              bool flag = false;
              for(int i = 0; i < 4; ++i){
                  int next_r = r + dir[i][0];
                  int next_c = c + dir[i][1];
                  vis[r][c] = true;
                  if(dfs(g, next_r, next_c)) flag = true;
                  vis[r][c] = false;
              }
              return flag;
          }
          int numEnclaves(vector<vector<int>>& grid) {
              nr = grid.size();
              nc = grid[0].size();
              vector<vector<bool>> _vis(nr, vector<bool>(nc, false));
              vis = _vis;
              int ans = 0;
              for(int i = 0; i < nr; i++){
                  for(int j = 0; j < nc; j++){
                      if(grid[i][j] == 1 && !dfs(grid, i, j)){
                              ans++;
                      } 
                  }
              }
              return ans;
          }
      };
      
    2. dfs O(mn)先淹周围

      class Solution {
      public:
          int nr, nc;
          void dfs(vector<vector<int>>& grid, int r, int c){
              if(r < 0 || r >= nr || c < 0 || c >= nc) return;
              if(grid[r][c] == 0) return;
      
              grid[r][c] = 0;
              
              dfs(grid, r + 1, c);
              dfs(grid, r - 1, c);
              dfs(grid, r, c + 1);
              dfs(grid, r, c - 1);
          }
          int numEnclaves(vector<vector<int>>& grid) {
              nr = grid.size(), nc = grid[0].size();
              for(int i = 0; i < nr; ++i){
                  if(grid[i][0] == 1) dfs(grid, i, 0);
                  if(grid[i][nc - 1] == 1) dfs(grid, i, nc - 1);
              }
              for(int j = 0; j < nc; ++j){
                  if(grid[0][j] == 1) dfs(grid, 0, j);
                  if(grid[nr - 1][j] == 1) dfs(grid, nr - 1, j);
              }
              int ans = 0;
              for(int i = 0; i < nr; ++i){
                  for(int j = 0; j < nc; ++j){
                      if(grid[i][j] == 1) ans++;
                  }
              }
              return ans;
          }
      };
      

695. 岛屿的最大面积

  • 思路+解法:

    1. DFS O(mn)

      class Solution {
      public:
          int ans = 0;
          int nr, nc;
          int cnt;
          void dfs(vector<vector<int>>& grid, int r, int c){
              if(r < 0 || r >= nr || c < 0 || c >= nc) return;
              if(grid[r][c] == 0) return;
      
              cnt++;
              if(cnt > ans) ans = cnt;
              grid[r][c] = 0;
              
              dfs(grid, r + 1, c);
              dfs(grid, r - 1, c);
              dfs(grid, r, c + 1);
              dfs(grid, r, c - 1);
          }
          int maxAreaOfIsland(vector<vector<int>>& grid) {
              nr = grid.size(), nc = grid[0].size();
              for(int i = 0; i < nr; i++){
                  for(int j = 0; j < nc; j++){
                      if(grid[i][j] == 1){
                          cnt = 0;
                          dfs(grid, i, j);
                      }
                  }
              }
              return ans;
          }
      };
      

1905. 统计子岛屿

  • 思路+解法:

    1. DFS O(mn)

      class Solution {
      private:
          int nr, nc;
      public:
          
          void dfs(vector<vector<int>>& grid2, int x, int y){
              if(x < 0 || x >= nr || y < 0 || y >= nc) return;
              if(grid2[x][y] == 0) return;
      
              grid2[x][y] = 0;
              dfs(grid2, x + 1, y);
              dfs(grid2, x - 1, y);
              dfs(grid2, x, y + 1);
              dfs(grid2, x, y - 1);
          }
          int countSubIslands(vector<vector<int>>& grid1, vector<vector<int>>& grid2) {
              nr = grid1.size();
              nc = grid1[0].size();
              for(int i = 0; i < nr; i++){
                  for(int j = 0; j < nc; j++){
                      if(grid2[i][j] == 1 && grid1[i][j] == 0){
                          dfs(grid2, i, j);
                      }
                  }
              }
              int ans = 0;
              for(int i = 0; i < nr; i++){
                  for(int j = 0; j < nc; j++){
                      if(grid2[i][j] == 1){
                          ans++;
                          dfs(grid2, i, j);
                      }
                  }
              }
              return ans;
          }
      };
      

694.

305.

图遍历

797. 所有可能的路径

  • 思路+解法:

    1. DFS 数组表示的邻接表 O(n∗2^n)

      class Solution {
      public:
          vector<vector<int>> ans;
          vector<int> path;
          void dfs(vector<vector<int>>& graph, int loc){
              if(loc == graph.size() - 1){
                  ans.push_back(path);
                  return;
              }
              for(int i = 0; i < graph[loc].size(); i++){
                  path.push_back(graph[loc][i]);
                  dfs(graph, graph[loc][i]);
                  path.pop_back();
              }
          }
          vector<vector<int>> allPathsSourceTarget(vector<vector<int>>& graph) {
              path.push_back(0);
              dfs(graph, 0);
              return ans;
          }
      };
      

拓扑排序

207.课程表

  • 思路+解法:

    1. 拓扑排序 O(n + m)

      class Solution {
      private:
          vector<int> indegree; //入度
          vector<vector<int>> edges;//储存边
      public:
          bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
              indegree.resize(numCourses);
              edges.resize(numCourses);
              for(int i = 0; i < prerequisites.size(); i++){
                  edges[prerequisites[i][1]].push_back(prerequisites[i][0]);
                  indegree[prerequisites[i][0]]++;
              }
              queue<int> q;
              vector<int>ans; //最终排序后的序列
      	    for(int i = 0; i < numCourses; i++)
              {
                  if(indegree[i] == 0) q.push(i);
              }
              while(!q.empty()){
          	    int x = q.front();
          	    q.pop();
          	    ans.push_back(x);
          	    for(int i = 0; i < edges[x].size(); i++){
          		    indegree[edges[x][i]]--;
          		    if(indegree[edges[x][i]] == 0) q.push(edges[x][i]);
      		    }
      	    }
              return ans.size() == numCourses;
          }
      };
      

210.课程表 II

  • 思路+解法:

    1. 拓扑排序 O(n + m)

      class Solution {
      public:
          vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
              vector<int> indegree(numCourses, 0);
              vector<vector<int>> g(numCourses);
              for(auto& x: prerequisites){
                  g[x[1]].emplace_back(x[0]);
                  indegree[x[0]]++;
              }
              queue<int> q;
              vector<int> ans;
              for(int i = 0; i < numCourses; i++){
                  if(indegree[i] == 0){
                      q.push(i);
                  }
              } 
              while(!q.empty()){
                  int course = q.front();
                  q.pop();
                  ans.emplace_back(course);
                  for(int i = 0; i < g[course].size(); i++){
                      int out = g[course][i];
                      if(indegree[out] >= 0) indegree[out]--;
                      if(indegree[out] == 0) q.push(out);
                  }
              }
              if(ans.size() == numCourses) return ans;
              return {};
          }
      };
      

最短路 Dijkstra

  • 稀疏图 - 邻接表、稠密图 - 邻接矩阵
  • 记堆的版本吧,毕竟nlogn

743. 网络延迟时间

  • 思路+解法:

    1. Dijkstra O(mlogm)

      class Solution {
      public:
          int networkDelayTime(vector<vector<int>>& times, int n, int k) {
              vector<vector<int>> g(n + 1, vector<int>(n + 1, 0x3f3f3f3f));
              vector<int> dis(n + 1, 0x3f3f3f3f);
              vector<int> used(n + 1, 0);
      
              for(auto& x : times){
                  g[x[0]][x[1]] = x[2];
              }
              //used[k] = 1; //得用第一个点更新一遍最短路径,要不然都是max
              dis[k] = 0;
      
              for(int i = 1; i <= n; i++){
                  int t = -1;
                  for(int j = 1; j <= n; j++){
                      if(!used[j] && (t == -1 || dis[t] > dis[j])) t = j;
                  }
                  used[t] = 1;
                  for(int j = 1; j <= n; j++){
                      if(dis[j] > dis[t] + g[t][j]){
                          dis[j] = dis[t] + g[t][j];
                      }
                  }
              }
      
              int ans = 0;
              for(int i = 1; i <= n; i++){
                  ans = max(ans, dis[i]);
              }
              return ans == 0x3f3f3f3f ? -1 : ans;
          }
      };
      

1514. 概率最大的路径

  • 思路+解法:

    1. Dijkstra O(mlogm)

      typedef pair<double, int> PDI;
      class Solution {
      public:
          double maxProbability(int n, vector<vector<int>>& edges, vector<double>& succProb, int start, int end) {
              vector<vector<pair<int, double>>> g(n);
              for (int i = 0; i < succProb.size(); i++) { /* 建立邻接表 */
                  g[edges[i][0]].emplace_back(edges[i][1], succProb[i]);
                  g[edges[i][1]].emplace_back(edges[i][0], succProb[i]);
              }
      
              vector<int> vis(n, 0);
      
              vector<double> por(n, 0); //到每个点的最大概率
      
              priority_queue<PDI, vector<PDI>, less<PDI>> q;
              por[start] = 1;
              q.push({1.0, start});
              while(!q.empty()){
                  PDI x = q.top();
                  q.pop();
      
                  int p = x.first;
                  int d = x.second;
      
                  if(vis[d]) continue;
                  vis[d] = true;
                  for (auto [v, w] : g[d]) {
                      if (por[v] < por[d] * w) {
                          por[v] = por[d] * w;
                          q.emplace(por[v], v);
                      }
                  }
                  for(int i = 0; i < g[d].size(); i++){
                      if(por[g[d][i].first] < por[d] * g[d][i].second){
                          por[g[d][i].first] = por[d] * g[d][i].second;
                          q.push({por[g[d][i].first], g[d][i].second});
                      }
                  }
              }
              return por[end]; 
          }
      };
      
  • 一点收获:

    1. 用邻接矩阵会超时,体现出什么时候用邻接矩阵、邻接表

1631. 最小体力消耗路径

  • 思路+解法:

    1. Dijkstra O(mnlog(mn))

      typedef pair<int, int> PII;
      class Solution {
      public:
          
          int minimumEffortPath(vector<vector<int>>& heights) {
              int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
              int n = heights.size();
              int m = heights[0].size();
      
              int ans = 0;
      
              vector<int> vis(n * m, 0);
              priority_queue<PII, vector<PII>, greater<PII>> heap;
      
              heap.push({0, 0});
              while(!heap.empty()){
                  PII d = heap.top();
                  heap.pop();
      
                  if(vis[d.second] == 1) continue;;
                  vis[d.second] = true;
                  
                  int x = d.second / m;
                  int y = d.second % m;
      
                  if(d.second == n * m - 1) return d.first;
                  //if(x == n - 1 && y == m - 1) return d.first;
      
                  for(int i = 0; i < 4; i++){
                      int next_x = x + dir[i][0];
                      int next_y = y + dir[i][1];
      
                      if(next_x < 0 || next_x >= n || next_y < 0 || next_y >= m || vis[next_x * m + next_y]) continue;
                      
                      heap.push({max(d.first, abs(heights[x][y] - heights[next_x][next_y])), next_x * m + next_y});
                  }
              }
              return 0;
          }
      };
      

最小生成树 Kruskal

261. 以图判树

1135. 最低成本联通所有城市

1584. 连接所有点的最小费用

  • 思路+解法:

    1. Kruskal O(mlogm)

      class Solution {
      
      //边的基本结构
      struct Edge{
          int a, b;
          int w;
          bool operator < (const Edge& W) const{
              return w < W.w;
          }
      };
      
      // 并查集操作
      vector<int> par;
      
      int find(int x){
          if(par[x] == x) return x;
          else return par[x] = find(par[x]);
      }
      
      public:
          int minCostConnectPoints(vector<vector<int>>& points) {
              vector<Edge> Edges;
              int n = points.size();
              int m = 0;
              //初始化边
              for(int i = 0; i < n; i++){
                  for(int j = 0; j < n; j++){
                      if(i != j){
                          Edges.push_back({i, j, abs(points[j][0] - points[i][0]) + abs(points[j][1] - points[i][1])});
                          m++;
                      }
                  }
              }
              sort(Edges.begin(), Edges.end());
      
              
              //初始化并查集
              par.resize(n);
              for(int i = 0; i < n; i++) par[i] = i;
      
              int cnt = 0, ans = 0;
              //从最小的边开始遍历
              for(int i = 0; i < m; i++){
                  int a = Edges[i].a, b = Edges[i].b, w = Edges[i].w;
                  a = find(a), b = find(b);
                  //如果不连通的话连通起来
                  if(a != b){
                      par[a] = b;
                      ans += w;
                      cnt++;
                  }
              }
              return ans;
          }
      };
      

二分图 染色法

785. 判断二分图

  • 思路+解法:

    1. 染色法 O(n + m)

      class Solution {
      private:    
          vector<int> color;
      
      public:
          bool dfs(vector<vector<int>>& g, int x, int c){
              color[x] = c;
              for(int i = 0; i < g[x].size(); i++){
                  int j = g[x][i];
                  if(color[j] == 0){
                      if(!dfs(g, j, -c)) return false;
                  }
                  else if(color[j] == c) return false;
              }
              return true;
          }
          bool isBipartite(vector<vector<int>>& graph) {
              int n = graph.size();
              color.resize(n);
              for(int i = 0; i < n; i++){
                  if(color[i] == 0){
                      if(!dfs(graph, i, 1)) return false;
                  }
              }
              return true;
          }
      };
      

886. 可能的二分法

  • 思路+解法:

    1. 染色法 O(n + m):

      class Solution {
      private:
          vector<int> color;
      public:
          bool dfs(vector<vector<int>>& g, int x, int c){
              color[x] = c;
              for(int i = 0; i < g[x].size(); i++){
                  int j = g[x][i];
                  if(color[j] == 0){
                      dfs(g, j, -c);
                  }
                  else if(color[j] == c) return false;
              }
              return true;
          }
          bool possibleBipartition(int n, vector<vector<int>>& dislikes) {
              color.resize(n + 1, 0);
              vector<vector<int>> g(n + 1);
              for(int i = 0; i < dislikes.size(); i++){
                  g[dislikes[i][0]].push_back(dislikes[i][1]);
                  g[dislikes[i][1]].push_back(dislikes[i][0]);
              }
              for(int i = 1; i <= n; i++){
                  if(color[i] == 0){
                      if(!dfs(g, i, 1)) return false;
                  }
              }
              return true;
          }
      };
      

BFS

752. 打开转盘锁

  • BFS O(10 ^ 4 * 4 ^ 2 + len * 4)

    class Solution {
    public:
        int openLock(vector<string>& deadends, string target) {
            unordered_set<string> vis;
            vis.insert(deadends.begin(), deadends.end());
            if(vis.count("0000")){
                return -1;
            }
            vis.insert("0000");
    
            queue<string> q;
            q.push("0000");
    
            int cnt = 0;
            while(!q.empty()){
                int size = q.size();
                for(int i = 0; i < size; i++){
    
                
                string s = q.front();
                q.pop();
                if(s == target) return cnt;
                
    
                //if(find(deadends.begin(), deadends.end(), s) != deadends.end()) continue;
    
                string s_copy = s;
                for(int i = 0; i < 4; i++){
                    if(s[i] == '9'){
                        s[i] = '0';
                        if(!vis.count(s)){
                            q.push(s);
                            vis.insert(s);
                        } 
                        s[i] = '9';
                        s[i] -= 1;
                        if(!vis.count(s)){
                            q.push(s);
                            vis.insert(s);
                        } 
                    }else if(s[i] == '0'){
                        s[i] += 1;
                        if(!vis.count(s)){
                            q.push(s);
                            vis.insert(s);
                        } 
                        s[i] = '0';
                        s[i] = '9';
                        if(!vis.count(s)){
                            q.push(s);
                            vis.insert(s);
                        } 
                    }else{
                        s[i] += 1;
                        if(!vis.count(s)){
                            q.push(s);
                            vis.insert(s);
                        } 
                        s[i] -= 1;
                        s[i] -= 1;
                        if(!vis.count(s)){
                            q.push(s);
                            vis.insert(s);
                        } 
                    }
                    s = s_copy;
                }
    
                }
                cnt++;
            }
            return -1;
        }
    };
    

773

127

数学运算技巧

191. 位1的个数

  • 思路+解法:

    1. 循环找最低位的1 O(logn)

      class Solution {
      public:
          int hammingWeight(uint32_t n) {
              int ans = 0;
              while(n != 0){
                  n = n & (n - 1);
                  ans ++;
              }
              return ans;
          }
      };
      

231. 2 的幂

  • 思路+解法:

    1. 2的倍数的话只有一个1 O(1)

      class Solution {
      public:
          bool isPowerOfTwo(int n) {
              if(n <= 0) return false;
              return (n & (n - 1)) == 0;
          }
      };
      

136. 只出现一次的数字

  • 思路+解法:

    1. 异或性质 O(n)

      class Solution {
      public:
          int singleNumber(vector<int>& nums) {
              int ans = 0;
              for(auto& x : nums) ans ^= x;
              return ans;
          }
      };
      

172.阶乘后的零

  • 思路+解法:

    1. 数学 O(logn)

      //计算末尾0转换为计算有多少个10->多少个2*5->多少个5
      //5贡献1个5,25贡献2个5,125贡献3个5..
      //查看有多少个5、25、125...的倍数
      class Solution {
      public:
          int trailingZeroes(int n) {
              int ans = 0;
              int x = 5;
              while(x <= n){
                  ans += (n / x);
                  x *= 5;
              }
              return ans;
          }
      };
      

793.阶乘后 K 个零

  • 思路+解法:

    1. 数学+二分找左右边界 O(lognlogn)

      class Solution {
      public:
          long long cal_zero(long long n){
              long long ans = 0;
              long long x = 5;
              while(x <= n){
                  ans += (n / x);
                  x *= 5;
              }
              return ans;
          }
      
          int preimageSizeFZF(int k) {
              long long ans1 = 0;
              long long ans2 = 0;
              long long l = 0, r = INT_MAX;
              while(l <= r){
                  long long mid = (r - l) / 2 + l;
                  long long tar = cal_zero(mid);
                  if(tar == k){
                      ans1 = mid;
                      r = mid - 1;
                  }else if(tar > k){
                      r = mid - 1;
                  }else if(tar < k){
                      l = mid + 1;
                  }
              }
      
              l = 0, r = INT_MAX;
              while(l <= r){
                  long long mid = (r - l) / 2 + l;
                  long long tar = cal_zero(mid);
                  if(tar == k){
                      ans2 = mid;
                      l = mid + 1;
                  }else if(tar > k){
                      r = mid - 1;
                  }else if(tar < k){
                      l = mid + 1;
                  }
              }
              if(ans2 == ans1) return 0;
              else return ans2 - ans1 + 1;
          }
      };
      
  • 亿点收获:

    1. **LONG_LONG_MAX **
    2. long long

204.计数质数

  • 思路+解法:

    1. 埃氏筛选 O(nloglogn)

      class Solution {
      public:
          int shai(int n){
              vector<int> v(n, 1);
              int ans = 0;
              v[0] = 0;
              v[1] = 0;
              for(int i = 2; i < n; i++){
                  if(!v[i]) continue;
                  ans++;
                  int x = i + i;
                  while(x < n){
                      v[x] = 0;
                      x = x + i;
                  }
              }
              return ans;
          }
          int countPrimes(int n) {
              if(n <= 2) return 0;
              return shai(n);
          }
      };
      

372. 超级次方

  • 思路+解法:

    1. 快速幂 O(logn)

      //a^1023 = (a^1000)^1 * (a^100)^0 * (a^10)^2 * (a^1)^3
      class Solution {
      public:
          int qpow(int a, int b){
              int ans = 1;
              int base = a;
              while(b > 0){
                  if(b & 1) ans = ans * base % 1337;
      
                  base = base * base % 1337;
                  b >>= 1;
              }
              return ans;
          }
          int superPow(int a, vector<int>& b) {
              int n = b.size();
              int ans = 1;
              a %= 1337;
              for(int i = n - 1; i >= 0; i--){
                  ans = ans * qpow(a, b[i]) % 1337;
                  a = qpow(a, 10) ;
              }
              return ans; 
          }
      };
      

268. 丢失的数字

  • 思路+解法:

    1. 位置和值异或

    2. 等差数列求和公式 Sn=n*a1+n(n-1)d/2或Sn=n(a1+an)/2

    3. 比较下标和元素值的合的差值

      class Solution {
      public:
          int missingNumber(vector<int>& nums) {
              int ans = nums.size();
              for(int i = 0; i < nums.size(); ++i){
                  ans +=  (i - nums[i]);
              }
              return ans;
          }
      };
      

645. 错误的集合

  • 思路+解法:

    1. 数组下标 O(n)

      class Solution {
      public:
          vector<int> findErrorNums(vector<int>& nums) {
              //一个元素对应下标,下标被重复访问则说明重复元素
              //没有被访问的下标说明缺失该数
              int dup, miss;
              for(int i = 0; i < nums.size(); i++){
                  int index = abs(nums[i]) - 1;
                  if(nums[index] < 0){
                      dup = index + 1;
                  }
                  else{
                      nums[index] *= -1;
                  }
              }
              for(int i = 0; i < nums.size(); i++){
                  if(nums[i] > 0){
                      miss = i + 1;
                  }
              }
              return {dup, miss};
          }
      };
      
    2. 异或运算 O(n)

      class Solution {
      public:
          vector<int> findErrorNums(vector<int>& nums) {
              int xorsum = 0;
              int n = nums.size();
              for(auto& x : nums) xorsum ^= x;
              for(int i = 1; i <= n; i++){
                  xorsum ^= i;
              }
              int a = 0, b = 0;
              int lowone = xorsum & (-xorsum);
              for(auto& x : nums){
                  if(x & lowone){
                      a ^= x;
                  }else{
                      b ^= x;
                  }
              }
              for(int i = 1; i <= n; i++){
                  if(i & lowone){
                      a ^= i;
                  }else{
                      b ^= i;
                  }
              }
              for(auto& x : nums){
                  if(a == x){
                      return {a, b};
                  }
              }
              return {b, a};
          }
      };
      

382. 链表随机节点

  • 解法+思路:

    1. 蓄水池抽样随机算法 O(n)

      /**
       * Definition for singly-linked list.
       * struct ListNode {
       *     int val;
       *     ListNode *next;
       *     ListNode() : val(0), next(nullptr) {}
       *     ListNode(int x) : val(x), next(nullptr) {}
       *     ListNode(int x, ListNode *next) : val(x), next(next) {}
       * };
       */
      class Solution {
      public:
          ListNode* head;
          Solution(ListNode* head) {
              this->head = head;
          }
          
          int getRandom() {
              int ans = -1;
              ListNode* node = head;
              int k = 1;
              while(node){
                  if(rand() % k == 0){
                      ans = node->val;
                  }
                  k++;
                  node = node->next;
              }
              return ans;
          }
      };
      
      /**
       * Your Solution object will be instantiated and called as such:
       * Solution* obj = new Solution(head);
       * int param_1 = obj->getRandom();
       */
      

398. 随机数索引

  • 解法+思路:

    1. 蓄水池抽样随机算法 O(n)

      class Solution {
      public:
          vector<int> nums;
          Solution(vector<int>& nums) : nums(nums) {
      
          }
          
          int pick(int target) {
              int ans = -1;
              int k = 1;
              for(int i = 0; i < nums.size(); i++){
                  if(nums[i] == target){
                      if(rand() % k == 0) ans = i;
                      k++;
                  }
              }
              return ans;
          }
      };
      
      /**
       * Your Solution object will be instantiated and called as such:
       * Solution* obj = new Solution(nums);
       * int param_1 = obj->pick(target);
       */
      

26.删除有序数组中的重复项

  • 思路+解法:

    1. 快慢指针 O(n)

      class Solution {
      public:
          int removeDuplicates(vector<int>& nums) {
              if(nums.size() == 0) return 0;
              int slow = 0, fast = 0;
              while(fast < nums.size()){
                  if(nums[slow] == nums[fast]){
                      fast++;
                  }else{
                      slow++;
                      swap(nums[slow], nums[fast]);
                      fast++;
                  }
              }
              return slow + 1;
          }
      };
      
      class Solution {
      public:
          int removeDuplicates(vector<int>& nums) {
              if(nums.size() == 0) return 0;
      
              int slow = 0, fast = 0;
              while(fast < nums.size()){
                  if(nums[slow] != nums[fast]){
                      slow++;
                      swap(nums[slow], nums[fast]);
                  }
                  fast++;
              }
              return slow + 1;
          }
      };
      

83.删除排序链表中的重复元素

  • 思路+解法:

    1. 快慢指针 O(n)

      /**
       * Definition for singly-linked list.
       * struct ListNode {
       *     int val;
       *     ListNode *next;
       *     ListNode() : val(0), next(nullptr) {}
       *     ListNode(int x) : val(x), next(nullptr) {}
       *     ListNode(int x, ListNode *next) : val(x), next(next) {}
       * };
       */
      class Solution {
      public:
          ListNode* deleteDuplicates(ListNode* head) {
              if(!head) return head;
              ListNode* slow = head, *fast = head;
              while(fast != nullptr){
                  if(slow->val != fast->val){
                      slow = slow->next;
                      swap(slow->val, fast->val);
                  }
                  fast = fast->next;
              }
              slow->next = nullptr;
              return head;
          }
      };
      

27.移除元素

  • 思路+解法:

    1. 快慢指针 O(n)

      class Solution {
      public:
          int removeElement(vector<int>& nums, int val) {
              int slow = 0, fast = 0;
              while(fast < nums.size()){
                  if(nums[fast] != val){
                      swap(nums[slow], nums[fast]);
                      slow++;
                      fast++;
                  }else{
                      fast++;
                  }
              }
              return slow;
          }
      };
      

283.移动零

  • 思路+解法:

    1. 快慢指针 O(n)

      class Solution {
      public:
          void moveZeroes(vector<int>& nums) {
              int slow = 0, fast = 0;
              while(fast < nums.size()){
                  if(nums[fast] != 0){
                      swap(nums[slow], nums[fast]);
                      slow++;
                      fast++;
                  }else{
                      fast++;
                  }
              }
          }
      };
      

292.Nim游戏

  • 思路+解法:

    1. 博弈 O(1)

      class Solution {
      public:
          bool canWinNim(int n) {
              return n % 4 != 0;
          }
      };
      

877.石子游戏

  • 思路+解法:

    1. 博弈 O(1)

      class Solution {
      public:
          bool stoneGame(vector<int>& piles) {
              return true;
          }
      };
      

319.灯泡开关

  • 思路+解法:

    1. 找规律 O(n)

      class Solution {
      public:
          //第i轮,每i个灯泡切换一次开关
          //第i个灯泡的反转次数等于它因子的个数
          //只有翻转奇数次才会亮
          int bulbSwitch(int n) {
              return sqrt(n);
          }
      };
      

标签:return,记录,int,++,vector,grid,ans,labuladong,刷题
来源: https://blog.csdn.net/weixin_45643285/article/details/122204771

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有