zoukankan      html  css  js  c++  java
  • 力扣_初级算法_设计问题_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


  • 相关阅读:
    【bzoj2821】作诗(Poetize)
    ZOJ-2112-Dynamic Rankings(线段树套splay树)
    POJ- 2104 hdu 2665 (区间第k小 可持久化线段树)
    hust-1024-dance party(最大流--枚举,可行流判断)
    hdu-3046-Pleasant sheep and big big wolf(最大流最小割)
    POJ-3294-Life Forms(后缀数组-不小于 k 个字符串中的最长子串)
    POJ-Common Substrings(后缀数组-长度不小于 k 的公共子串的个数)
    POJ-2774-Long Long Message(后缀数组-最长公共子串)
    POJ-3693-Maximum repetition substring(后缀数组-重复次数最多的连续重复子串)
    spoj-694-Distinct Substrings(后缀数组)
  • 原文地址:https://www.cnblogs.com/Wang-dou-dou/p/13290828.html
Copyright © 2011-2022 走看看