力扣_初级算法_设计问题_1~2题_和_数学_1~4题_和_其他_1题

一位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.

提示:

  • poptop 和 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. 如果 是3的倍数,输出“Fizz”;

2. 如果 是5的倍数,输出“Buzz”;

3.如果 同时是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题:计数质数

题目描述:

统计所有小于非负整数 的质数的数量。

举例:

示例:

输入: 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, LCD 和 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


原文地址:https://www.cnblogs.com/Wang-dou-dou/p/13290828.html