189. 旋转数组

分析

1 2 3 4 5 6 7
向右边移动3位
5 6 7 1 2 3 4

移动k次, 相当于后面k个数移动到前面
当然先要对 k % n先
原地算法
当然想用原地算法的话, 每次移动1个, 移动k次, 这样时间复杂度O(n^2)

因为移动1次要搬运n - 1个数, k次的话要搬k(n - 1)次

将数组翻转的话, 可以用原地算法来做
第1次交换 第1, 第n - 1
2次交换, 第2, 第n - 2个数
当两个指针相遇的时候, 就结束了

所以可以原地算法翻转一段

那么能不能用翻转操作 实现题目的要求呢

先把整个数组翻转一遍

翻转完后, 左边是逆序的, 右边是逆序的
然后分别对左边做翻转, 右边做翻转

翻转2倍, O(n), 空间O(1)

code

class Solution {public:void rotate(vector<int>& nums, int k) {int n = nums.size();k %= n;reverse(nums.begin(), nums.end()); // 先翻转整个字符串reverse(nums.begin(), nums.begin() + k); // 翻转前面部分reverse(nums.begin() + k, nums.end()); // 翻转后面那部分}
};

190. 颠倒二进制位

分析

有一种方式,
int -> string -> reverse - >int

但是有一种更简单的方式, 可以省去中间部分(string->reverse)
直接将int -> int

首先考虑如何取int的第k位
n >> k & 1

先取个位,放到新的最高位, 然后取十位, 放到新的第2位
假如答案是res, 相当于是在答案末尾+1位
res << 1(先将最后1位空出来) + (n >> k & 1) (加入当前位数)

code

class Solution {public:uint32_t reverseBits(uint32_t n) {uint32_t res = 0;for (int i = 0; i < 32; i ++ )res = res * 2 + (n >> i & 1);return res;}
};

191. 位1的个数

分析

每一位数判断, 每次对n可以/2, 所以logn

code (O(logn))

class Solution {public:int hammingWeight(uint32_t n) {int res = 0;for (int i = 0; i < 32; i ++ )res += (n >> i & 1);return res;}
};

分析(lowbit)

lobit会返回2进制最后1位1
x=13=(1101)2x = 13 = (1101)_2x=13=(1101)2​ , 那么lowbit(x) 会返回(1)2(1)_2(1)2​
x=12=(1100)2x = 12 = (1100)_2x=12=(1100)2​ , 拿了lowbit(x) 会返回(100)2(100)_2(100)2​, 就是返回(8)10(8)_{10}(8)10​

计算次数稍微少1些, 因为计算次数等于包含1的个数,
只有1个1的话, 只用计算1次, 不需要枚举32次

code(lowbit)

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

198. 打家劫舍

分析

不能选相邻的
简单的dp

code

下标从1开始,

class Solution {public:int rob(vector<int>& nums) {int n = nums.size();vector<int> f(n + 1), g(n + 1);for (int i = 1; i <= n; i ++ ){f[i] = g[i - 1] + nums[i - 1];// nums0开始所以错开g[i] = max(f[i - 1], g[i - 1]);}return max(f[n], f[n - 1]);}
};

199. 二叉树的右视图

分析

求从右边往左看的值.
注意: 不是求右链
因为可能是以下情况

所以就是用宽搜, 搜下每一层, 将每一层最后一个数记下来就可以了

code

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {public:vector<int> rightSideView(TreeNode* root) {if (!root) return {};queue<TreeNode*> q;q.push(root);vector<int> res;while (q.size()){int len = q.size();for (int i = 0; i < len; i ++ ){auto t = q.front(); q.pop();if (t->left) q.push(t->left);if (t->right) q.push(t->right);if (i == len - 1) res.push_back(t->val);}}return res;}
};

200. 岛屿数量

分析

code

class Solution {public:int n, m;int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};int numIslands(vector<vector<char>>& grid) {n = grid.size(), m = grid[0].size();int res = 0;for (int i = 0; i < n ; i ++ )for (int j = 0; j < m; j ++ )if (grid[i][j] == '1') {res ++;dfs(grid, i, j);}return res;}void dfs(vector<vector<char>>& grid, int x, int y){grid[x][y] = '0';for (int i = 0; i < 4; i ++ ){int a = x + dx[i], b = y + dy[i];if (a >= 0 && a < n && b >= 0 && b < m && grid[a][b] == '1') dfs(grid, a, b);}}
};

201. 数字范围按位与

分析

脑筋急转弯, 看下
大概看下数据范围, m≤nm \leq nm≤n
假设m和n的前k个都是一样的

m = xxxxxx0…
n = xxxxxx1…

可以发现 xxxxxx0… 中最大数就是xxxxxx011111, 那么xxxxxx011111 >= m, (因为是m所有选择中最大的啊)

同理xxxxxx100000 <= n, 因为xxxxxx100000是最小的一个,
所以可以发现
xxxxxx011111
xxxxxx100000
必然是在[m, n]之间, 由于&运算有交换律, 所以先对这两个数&, 后面全是0

所以这题答案就有了, 找到m和n第1位答案不一样的地方, 从这1位不一样的地方到后面, 全部都是0, 前面都不变

code

class Solution {public:int rangeBitwiseAnd(int m, int n) {int res = 0;for (int i = 30; i >= 0; i -- ){ // 从最高位开始枚举if ((m >> i & 1) != (n >> i & 1)) break;if (m >> i & 1) res += 1 << i;}return res;}
};

202. 快乐数

分析

最坏情况下, 假设有10个9, 999999999 也就是每次变完之后 = 92∗10=8109^2 * 10 = 81092∗10=810
所以每次操作完必然是0~810之间的数
那就是说数的个数不到1000个
所当操作812次之后, 必然会陷入循环
问题就是问 最后结束的地方是否是1

怎么去遍历圈呢
其实就是判断圈里是不是就是只有1个数1, 如果有1的话, 必然会自己循环
不可能有多个圈, 因为每个数变成的数是唯一的, 如果有多个圈的话, 交点就会有2个数, 矛盾了

同环形链表那里一样

同学课堂疑问: 不太懂, 为什么会有重复

yxc: 0 ~ 810一共811个数, 但是走了812步的话, 必然是出现812个不同的数, 总共只有811个不同的数, 因此一定重复了

联动题

leetcode141, 142

回到本题

所以可以用双指针来做, 一个慢指针, 一个快指针, 慢指针每次走1步, 快指针每次走2步, 当两个指针相遇的时候, 必然是环中的某个点, 判断下这个点是不是1

code

class Solution {public:int get(int x){int res = 0;while (x){res += (x % 10) * (x % 10);x /= 10;}return res;}bool isHappy(int n) {int slow = n, fast = get(n); // 注意刚开始fast先走一步// 否则无法进入while循环while (slow != fast){fast = get(get(fast)), slow = get(slow); // fast走两部, slow走一步}return fast == 1;}};

203. 移除链表元素

分析

每次从虚拟头节点开始遍历, 看下头节点的下一个点开始的一段 = 目标值的都略去
如果不等于的, 不用管,

code

/*** 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* removeElements(ListNode* head, int val) {auto dummy = new ListNode(-1);dummy->next = head;for (auto p = dummy; p; p = p->next){auto q = p->next; // 每次从当前点的下一个点开始搜while (q && q->val == val) q = q->next; // 如果==val, 就跳过p->next = q; // 然后让p指向q}return dummy->next;}
};

204. 计数质数

分析

首先一个判重数组, 来判断1 ~ n中这些数是不是被筛选过
所谓被筛过就是: 如果不是质数的话就打上标记true

正确性:

之所以是O(n)的, 是因为保证了每个和数一定会被最小值质因子筛, 并且值会被最小值质因子筛

线性筛法: 每个合数 N, 一定会被且只会被最小质因子筛, 而且只会被筛1次
这样的话, 只要证明这一点, 就能保证每个和数都会被筛掉, 一定会被筛的话, 那就证明了线性筛是正确的, 再一个就是每个和数有唯一的最小质因子, 且只会被最小质因子筛1次, 所以每个数只会被筛1次, 所以可以保证时间是O(n)的

每个数只会被筛1次, for (int j = 0; i * primes[j] < n; j ++ ) 加到一块只会循环n

首先, 一个质数一定不会被筛, i * primes[j]乘积一定是一个和数, 因为起码两个质因子
再一个

1.每个合数一定会被筛

假设: 合数用N表示, p是N的最小质因子

让i=npi = \frac{n}{p}i=pn​, 由于p是N的最小质因子
那么iii的质因子, 一定是N的质因子, 因为i是N的约数, 所以i里面每个质因子, 一定是N的质因子
所以p≤ip \leq ip≤i的所有质因子

for (int i = 2; i < n; i ++ ) 循环到n/pn / pn/p的时候, 即循环到iii的时候, 因为ppp是N的最小质因子, 又因为iii是N的约数, 所以p≤ip \leq ip≤i的所有质因子,
所以p≤ip \leq ip≤i, 就一定会有ppp这个质因子一定被找出来了, 一定已经在primes里了
然后在从小到大枚举质因子的时候, (for (int j = 0; i * primes[j] < n; j ++ ) 这句话, 从小到大枚举质因子), 由于p≤ip \leq ip≤i的所有质因子, 所以不可能存在比ppp小的质因子primes[j], 使得(i % primes[j] == 0), 所以一定不会在p之前break

为什么可能存在比p小的质数因子呢, 因为i的所有质因数分解里的质数都要 >= p了, 最少也是p, 因此就不可能存在比p还小的数能够整除i

因此for (int j = 0; i * primes[j] < n; j ++ ) 循环中, primes[j]一定会枚举到ppp

一定会枚举到ppp的话, 那么i∗pi * pi∗p一定会被筛掉, N=Np∗pN = \frac{N}{p} * pN=pN​∗p 一定会被筛掉(这里把 i=Npi = \frac{N}{p}i=pN​代入了)

2.合数N会被最小质因子筛几次(N是不是只会被最小质因子筛)

由于 if (i % primes[j] == 0) 一定会break, 然后p[j]是从小到大枚举的

所在执行st[i * primes[j]] = true;这句话的时候, 一定会有 pjp_jpj​ 一定 ≤\leq≤ i的所有质因子

因为如果说pj>ip_j > ipj​>i的某个质因子的话, 当枚举到iii的质因子的时候, 就会执行if (i % primes[j] == 0) 会break, 就会跳出j的循环, 枚举不到pjp_jpj​了

因此pjp_jpj​一定是pj∗ip_j * ipj​∗i的最小质因子
所以就证明了 只会被最小的质因子pjp_jpj​筛

3.只会被筛1次

N只会在i=Npi = \frac{N}{p}i=pN​, 且jjj 枚举到pjp_jpj​的时候筛1次, 所以N只会被筛1次

code O(n)

class Solution {public:int countPrimes(int n) {vector<bool> st(n + 1);vector<int> primes;for (int i = 2; i < n; i ++ ){if (!st[i]) primes.push_back(i); // 如果没被标记过, 那一定是质数// 因为上面说了啊, 标记过的都不是质数了, 那么剩下的没标记的都一定是质数了for (int j = 0; i * primes[j] < n; j ++ ){st[i * primes[j]] = true;if (i % primes[j] == 0) break;}}return primes.size();}
};

Week 10. 第189-204题相关推荐

  1. 美团校招-2023.3.18.10点-第四题-商店-困难

    商店 Problem Description 在商店里有N个物品,每个物品有原价和折扣价小美相要购买商品.小美拥有X元,一共Y张折扣券.小美需要最大化购买商品的数量,并在所购商品数量尽量多的前提下,尽 ...

  2. 10以内逆向运算题_Z3在逆向中运用

    亲爱的,关注我吧 9/17 文章共计7370个词 预计阅读10分钟 来和我一起阅读吧 介绍 Z3 在工业应用中实际上常见于软件验证.程序分析等.然而由于功能实在强大,也被用于很多其他领域.CTF 领域 ...

  3. 10.8 wtx模拟题题解

    填坑 orz w_x_c_q w_x_c_q的模拟赛(150pts,炸了) money 题目背景: 王小呆又陷入自己的梦里.(活在梦里...) 题目描述: 王小呆是一个有梦想的小菜鸡,那就是赚好多好多 ...

  4. 10以内逆向运算题_加减法启蒙系列 | 实战篇二(10以内减法)

    如果你喜欢本文,欢迎分享到朋友圈和聊天群.未经允许,请勿转载,否则视为侵权! 这是我加减法启蒙的第三篇,前两篇着重介绍了"加减法启蒙的前期准备"以及"10以内加法启蒙的实 ...

  5. AcWing蓝桥杯AB组辅导课10、疑难杂题

    文章目录 前言 例题1:AcWing 1242. 修改数组(并查集) 分析 题解:单链表式并查集 例题2:AcWing 1234. 倍数问题(背包问题+贪心) 分析 题解1:01背包问题,三维解法(贪 ...

  6. 2022.10.14每日刷题打卡

    リモコン 题意: 题目描述: 高桥君要调整空调的设定温度.现在的设定温度是A度,而他想调到B度. 空调遥控器按一次可以: 上调或下调1度 上调或下调5度 上调或下调10度 高桥君想求出从A调到B度的最 ...

  7. 2017.10.27涩会题大乱斗部分题解

    A P3741 honoka的键盘 和昨天的T1一样, 枚举改哪一个 1 #include<cstdio> 2 #include<cstring> 3 #include< ...

  8. 10.9 guz模拟题题解

    感谢@guz 顾z的题题解 考试共三道题,其中 第一题help共10个测试点,时间限制为 1000ms,空间限制为 256MB. 第二题escape共20个测试点,时间限制为1000ms2000ms, ...

  9. 计算机新生必看:10道逻辑思维训练题,做完让你成为大佬!!(附带答案)

    前言:学会编程,不仅可以提高一个人的智商水平,锻炼人的思维能力,还可以成为一个人谋生的技能. 弄懂以下10道锻炼编程思维的题,可以快速提高您的思维能力,快速上手编程. 一.有口井7米深,有一个蜗牛从井 ...

  10. linux c int16进制转10进制,[编程题] 进制转换(16进制转10进制)

    [编程题] 进制转换 3/3 [编程题] 进制转换 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M 写出一个程序,接受一个十六进制的数,输出该数值的十进制表示. ...

最新文章

  1. splunk 通过rest http导入数据
  2. SOP,TSSOP,PLCC,BGA这些封装的中英文解释
  3. ubuntu卸载nvidia驱动_解决Ubuntu18.04循环登录问题 - 卸载NVIDIA驱动 启用Nouveau(1)
  4. JAVA语法基础 动手动脑及课后作业
  5. 计算机考研:河南有哪些性价比高的学校?
  6. 【SIS-OAS 1.52.0】【C03-测试报告】常规版本回归测试报告-------回归测试报告模板...
  7. 10分钟读懂人工智能、机器学习到底有什么关系
  8. ssm使用全注解实现增删改查案例——mybatis-config.xml
  9. JDBC——编程式事务的实现逻辑
  10. 直接写和放在函数中不同的R语言用法
  11. react16.8+的生命周期
  12. python做数据可视化视频_Python数据分析系列视频课程--玩转数据可视化
  13. 泸州职称计算机,2018年11月四川泸州职称计算机考试10月8日开始报名
  14. ApacheCN Asp.NET 译文集 20211126 更新
  15. linux下进程调度算法实验,Linux下进程调度算法的模拟实现.doc
  16. 六个国外免费的DNS服务-做英文与外贸必备
  17. struts2中的addActionError addFieldError addActionMessage的方法
  18. testmeshpro合批_UGUI合批原理笔记
  19. CAD导入MAXWELL
  20. 解决Kaggle新用户注册无法弹出验证提示的问题

热门文章

  1. 联想服务器改win7系统教程,手把手教你联想win11改win7系统教程
  2. 图片格式tif转换jpg
  3. ico在线制作,网站小图标Favicion.ico在线制作工具软件
  4. 推荐一个在线的icon图片合成工具(CSS Sprite)
  5. 爬取斗鱼4300W热度的小姐姐是一种什么样的体验?
  6. 从零开始学习CANoe(二)—— CANdb++ 创建 dbc文件
  7. autocad ios 虚线_教大家AutoCAD2020怎么画虚线的方法
  8. Android shape半圆,1/4圆
  9. Mac 技巧|忘记了开机密码的解决办法
  10. 苹果电脑忘记开机密码怎么办?一段代码轻松解决