一位C++小白的力扣刷题_成长记录_欢迎 visit ^_^
( 该篇,以及后面的随笔,都将加入一个“运行结果” 。 不断完善,加油加油~!)
设计问题_第1题:打乱数组
题目描述:
打乱一个没有重复元素的数组。
举例:(说实话,刚开始,我没看懂它的例子)
示例:
// 以数字集合 1, 2 和 3 初始化数组。 int[] nums = {1,2,3}; Solution solution = new Solution(nums); // 打乱数组 [1,2,3] 并返回结果。任何 [1,2,3]的排列返回的概率应该相同。 solution.shuffle(); // 重设数组到它的初始状态[1,2,3]。 solution.reset(); // 随机返回数组[1,2,3]打乱后的结果。 solution.shuffle();
补充:( 题目要求的,C++的执行语句 )
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(nums);
* vector<int> param_1 = obj->reset();
* vector<int> param_2 = obj->shuffle();
*/
解题思路:就一个思想,“随机交换”。
学习心得:①这道题,卡我半天,主要就是在理解题目上。这道题的里面的所有“一维的vector容器”,
只装3个元素( 不一定是“3”,只是这个样例是“3”,对于其他例子,视情况而定)。所以就只是在
装有3个元素的“一维vector容器”里面,随机交换,使用“洗牌算法”。
②还有一点值得提的是,第一做这种“设计问题”,有点像设计一个“产品”,但这个“小产品”
只有两个功能,一个“reset”(重置),另一个“shuffle”(打乱)。
实现:(C++)
class Solution {
private:
vector<int> nums_1;
public:
Solution(vector<int>& nums) { //构造函数,将 传入的形参nums 给 私有成员nums_1 赋值
nums_1=nums;
}
/** Resets the array to its original configuration and return it. */
vector<int> reset() { //重置函数:将 私有成员nums_1 返回。注:nums_1里面 从初始化后 一直保存着最原始的数据
return nums_1;
}
/** Returns a random shuffling of the array. */
vector<int> shuffle() {
vector<int> v=nums_1; //新建立一个 “一维vector容器 v ”,将 私有成员nums_1 赋值给v
//这里再次说明一下,在以前的随笔中也提到过 :
//vector是C++的标准库函数,类似于“stdio.h”。它是个“容器”,想进一步了解vector,推荐去看B站的 企业级开发经理 的一节课 https://www.bilibili.com/video/BV1at41147p8
int i,j;
int len=v.size(); //若针对于这道题的样例,len为3
for( i=1;i<len;i++ ) //从i=1开始
{
j=rand()%(i+1); // j的随机取值范围为 [0,i] 。补充rand()函数知识:
// 若 result = a+rand()%(b-a+1) , 则 result的取值范围为 [a,b]
if( j!=i ) swap( v[j],v[i] ); //如果随机取值完后,j 的值和 区间[0,i] 的右边界i不等,则交换两个不同下标对应的元素
}
return v; //最后返回 “打乱”了的 容器v
}
};
运行结果: 说明: “我的输入”里面,Solution 对应 [ [ 1,2,3 ] ] 。shuffle 对应 [ ] 。后面的 reset 和 shuffle 也是对应 [ ]。
答案里面的 null 表示 未返回东西(因为 Solution 是构造函数 ,故不返回东西 )。“ 我的答案”里面,第一个 “ [ 1,3,2 ] ”是 第一次执行 shuffle 返回的东西。
代码执行结果:
我的输入
["Solution","shuffle","reset","shuffle"] [[[1,2,3]],[],[],[]]
我的答案
[null,[1,3,2],[1,2,3],[1,3,2]]
预期答案
[null,[3,1,2],[1,2,3],[1,3,2]]
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
设计问题_第2题:最小栈
题目描述:
设计一个支持 push
,pop
,top
操作,并能在常数时间内检索到最小元素的栈。
push(x)
—— 将元素 x 推入栈中。pop()
—— 删除栈顶的元素。top()
—— 获取栈顶元素。getMin()
—— 检索栈中的最小元素。
举例:
示例:
输入: ["MinStack","push","push","push","getMin","pop","top","getMin"] [[],[-2],[0],[-3],[],[],[],[]] 输出: [null,null,null,null,-3,null,0,-2] 解释: MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.getMin(); --> 返回 -3. minStack.pop(); minStack.top(); --> 返回 0. minStack.getMin(); --> 返回 -2.
提示:
pop
、top
和getMin
操作总是在 非空栈 上调用。
解题思路:灵活运用 栈(stack) 的 “后进先出”(类似于一个 月饼筒 ,后放进去的月饼先拿出来,而先放进去的只能等 前面的拿出来才行)。
另外构造一个 “辅助栈” ,用来储存最小值。
学习心得:这个,另外构造一个“辅助栈”,让我回忆起 初中高中数学的 辅助线。(但好像没什么关联)
主要就是,一个设计问题。想方设法地运用 已知的 “元件”,设计一个“产品”,具有某些“功能”。
实现:(C++)
class MinStack {
private:
stack<int> sta; //sta:stack的缩写(只是 我自己这样写的)
stack<int> helper_sta; //构造一个辅助栈
public:
/** initialize your data structure here. */
MinStack() {
helper_sta.push( INT_MAX ); //放一个 最大数(INT_MAX 是 int类型的最大整数) 进去,用于后面的比较
}
void push(int x) {
sta.push( x ); //放一个x进入 栈(这里不是辅助栈)
helper_sta.push( min( x,helper_sta.top() ) ); //先用min()函数比较 x 和 辅助栈的栈顶元素 的值,取比较后的较小值放入 辅助栈的栈顶
//这样的话, 无论如何,辅助栈的栈顶 始终是最小元素
}
void pop() {
sta.pop();
helper_sta.pop(); //同时也要把 辅助栈的栈顶元素弹出(即删除)
}
int top() {
return sta.top();
}
int getMin() {
return helper_sta.top(); //获取 栈 的最小元素(其实也是辅助栈的最小值)
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(x);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
运行结果: 说明:和上一道 设计问题的运行结果 的说明 类似。
代码执行结果:
我的输入
["MinStack","push","push","push","getMin","pop","top","getMin"] [[],[-2],[0],[-3],[],[],[],[]]
我的答案
[null,null,null,null,-3,null,0,-2]
预期答案
[null,null,null,null,-3,null,0,-2]
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
数学_第1题:Fizz Buzz
题目描述:
写一个程序,输出从 1 到 n 数字的字符串表示。
1. 如果 n 是3的倍数,输出“Fizz”;
2. 如果 n 是5的倍数,输出“Buzz”;
3.如果 n 同时是3和5的倍数,输出 “FizzBuzz”。
举例:
示例:
n = 15, 返回: [ "1", "2", "Fizz", "4", "Buzz", "Fizz", "7", "8", "Fizz", "Buzz", "11", "Fizz", "13", "14", "FizzBuzz" ]
解题思路:这道题不难。主要是一个 to_string( )函数的运用。
学习心得:终于刷到一道“简单”点儿的题了。
实现:(C++)
class Solution {
public:
vector<string> fizzBuzz(int n) {
vector<string> v(n,""); //构造一个“vector属性,装有string类型的”容器v,并开辟一个能储存n的元素的空间,每个小空间赋值""(空)。
int i;
for( i=1;i<=n;i++ )
{
if( i%3==0&&i%5==0 )
v[i-1]="FizzBuzz";
else if( i%3==0 )
v[i-1]="Fizz";
else if( i%5==0 )
v[i-1]="Buzz";
else
v[i-1]=to_string(i); //主要这里,运用 to_string( 数据 )。其功能是将括号里的数据(无论int型还是double型等等)转变成string类型
}
return v;
}
};
运行结果:
代码执行结果:
我的输入
1
我的答案
["1"]
预期答案
["1"]
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
数学_第2题:计数质数
题目描述:
统计所有小于非负整数 n 的质数的数量。
举例:
示例:
输入: 10 输出: 4 解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
解题思路:C语言教材中,有关于 “ 计数质数 ” 的 算法。其中质数判断的基本思路是:对于正整数 n ( n>1 ) ,取除以 2~√ n。如果能 “整除以” (表示得不是很清楚哈...),
则 n 不是质数。 这道题只需要多加一层 for 循环即可。
学习心得:有时候,一些数学结论(或理论)能极大地 简化一个算法。比如这道。在上面的解题思路中,本身
应该除以 2~n 的,但是数学结论告诉我们,只用除以 2~√ n 来判断即可。
实现:(C++)
class Solution {
public:
int countPrimes(int n) {
if( n==0||n==1 ) return 0; //特殊的两个数,单独提出
int i,j,k,count=0,flag; //flag作为标记,一旦 除以 2~√n 有除的尽的情况,改变标记。
for( j=2;j<n;j++ )
{
flag=0;
k=(int)sqrt(j); //k 为 j 的开方
for( i=2;i<=k;i++ )
if( j%i==0 )
{
flag=1;
break;
}
if(flag!=1) count++; //若改变了标记,说明 这层循环里面的 j 不是质数,不用 count++ 。
}
return count;
}
};
运行结果:
代码执行结果:
我的输入
10
我的答案
4
预期答案
4
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
数学_第3题:3的幂
题目描述:
给定一个整数,写一个函数来判断它是否是 3 的幂次方。
举例:
示例 1:
输入: 27 输出: true
示例 2:
输入: 0 输出: false
示例 3:
输入: 9 输出: true
示例 4:
输入: 45 输出: false
解题思路:这道题也不难。只是有一个 小小的“逆思维”(在我的那个解法里面)。
学习心得:虽然题简单,但我还是提交了几次才成功。认真地对待事,事才可能认真地给你成功的答复。
实现:(C++)
class Solution {
public:
bool isPowerOfThree(int n) {
int i=1;
while( n>=i )
{
if( n==i ) return true;
if( i>=INT_MAX/3 ) return false; //这句话 和 下面一句 是得有先后顺序的哈
//先前提到的“逆思维”就是,用 i 与 INT_MAX/3 去比较。避免 i=i*3 后,i 超过 int 能表示的范围
i*=3;
}
return false;
}
};
运行结果:
代码执行结果:
我的输入
27
我的答案
true
预期答案
true
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
数学_第4题:罗马数字转整数
题目描述:
罗马数字包含以下七种字符: I
, V
, X
, L
,C
,D
和 M
。
字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000
例如, 罗马数字 2 写做 II
,即为两个并列的 1。12 写做 XII
,即为 X
+ II
。 27 写做 XXVII
, 即为 XX
+ V
+ II
。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII
,而是 IV
。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX
。这个特殊的规则只适用于以下六种情况:
I
可以放在V
(5) 和X
(10) 的左边,来表示 4 和 9。X
可以放在L
(50) 和C
(100) 的左边,来表示 40 和 90。C
可以放在D
(500) 和M
(1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。
举例:
示例 1:
输入: "III" 输出: 3
示例 2:
输入: "IV" 输出: 4
示例 3:
输入: "IX" 输出: 9
示例 4:
输入: "LVIII" 输出: 58 解释: L = 50, V= 5, III = 3.
示例 5:
输入: "MCMXCIV" 输出: 1994 解释: M = 1000, CM = 900, XC = 90, IV = 4.
解题思路:运用 C++里面的 maps标准模板库 ,给每一个 罗马符号 映射 成对应的数字。然后设计算法,依次扫描该字符串。
学习心得:今天最大的收获就是 自学习到了 C++里面的maps标准模板库。感觉自己又习得了一套“武功”,
虽然还不够熟练,但很开心~!
实现:(C++)
class Solution {
public:
int romanToInt(string s) {
if( s.empty() ) return 0;
map<char,int> LM_tran_SZ={ //初始化哈希表( 力扣题解里有些前辈这样叫的 )
{'I',1},
{'V',5}, //注意 格式,每个映射组之间用 “,” 隔开
{'X',10},
{'L',50},
{'C',100},
{'D',500},
{'M',1000}
}; //最后要加上 “;”
int i,res=0,len=s.size();
for( i=0;i<len;i++ )
{
if( LM_tran_SZ[ s[i] ] >= LM_tran_SZ[ s[i+1] ] ) // 举个栗子:输入“VIII” ,则 LM_tran_SZ[ s[0] ] 相当于 LM_tran_SZ[ 'V' ],
// 进而 LM_tran_SZ[ 'V' ]=5。 另外,i+1不会导致越界,因为字符串string是以' '结尾的。其ASCII码为0,比其他任何字符的ASCII码都小。
res+=LM_tran_SZ[ s[i] ]; // 如果前者大于后者,res加上该“东西”
else
res-=LM_tran_SZ[ s[i] ]; // 如果前者小于后者,res减去该“东西”
}
return res;
}
};
运行结果:(C++)
代码执行结果:
我的输入
"III"
我的答案
3
预期答案
3
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
其他_第1题:位1的个数
题目描述:
编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
举例:
示例 1:
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
示例 2:
输入:00000000000000000000000010000000 输出:1 解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。
示例 3:
输入:11111111111111111111111111111101 输出:31 解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。
解题思路:灵活运用 位运算 。
学习心得:自学了位运算符号( & 、^ 、| 、~ 、>> 、<< )。感觉有时候 用位运算可以
大大提高程序的运算速度。(以下内容摘自CSDN,博主Lpy_Now )我们经常用>>1来代替
/2(div 2),比如二分查找、堆的插入操作等等。想办法用>>代替除法运算可以使程序的效率
大大提高。最大公约数的二进制算法用除以2操作来代替慢的出奇的%(mod)运算,效率可以提高60%。
实现:(C++)
class Solution {
public:
int hammingWeight(uint32_t n) { //uint32_t 表示 无符号的32位(即意思是能表示32位)的int类型
int res=0;
while( n>0 )
{
res+=n%2; //如果除余结果为 1 时( 即把 n 的二进制表示后,其末尾为1时),则 res加 1
n>>=1; //n 右位移 1位。 举个栗子: 0011 表示 3,则 3>>1 表示 001 ,结果为 1。是不是就相当于 3/2,其结果为 1
}
return res;
}
};
运行结果:
代码执行结果:
我的输入
00000000000000000000000000001011
我的答案
3
预期答案
3