c++初级算法训练

算法题来源力扣

数组

删除排序数组中的重复项

买卖股票的最佳时机 II

旋转数组

存在重复元素

只出现一次的数字

两个数组的交集 II

加一

移动零

两数之和

有效的数独

旋转图像

字符串

反转字符串

整数反转

字符串中的第一个唯一字符

有效的字母异位词

验证回文串

字符串转换整数 (atoi)

实现 strStr()

外观数列

最长公共前缀

链表

删除链表中的节点

删除链表的倒数第N个节点

反转链表

合并两个有序链表

回文链表

环形链表

二叉树的最大深度

验证二叉搜索树

对称二叉树

二叉树的层序遍历

将有序数组转换为二叉搜索树

排序和搜索

合并两个有序数组

第一个错误的版本

动态规划

爬楼梯

买卖股票的最佳时机

最大子序和

打家劫舍

设计问题

打乱数组

最小栈

数学

Fizz Buzz

计数质数

3的幂

罗马数字转整数

其他

位1的个数

汉明距离

颠倒二进制位

杨辉三角

有效的括号

缺失数字

第一个错误的版本

数组题

/*-------------------------------------------------------------------------------------------------------------------*/

1、删除排序数组中的重复项

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。

不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

class Solution {

public:

    int removeDuplicates(vector<int>& nums) {

        int len = nums.size(),temp =nums[0],ret = 1;

        for(int i = 1;i < len;i++ )

        {

            if(nums[i] != temp)

            {

                temp = nums[i];

                nums[ret] = temp;

                ret++;

            }

        }

        return ret;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

2、买卖股票的最佳时机 II

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

class Solution {

public:

    int maxProfit(vector<int>& prices) {

        int profit = 0,len = prices.size(),temp=0;

        for(int i = 1;i <len;i++)

        {

            temp = prices[i]-prices[i-1];

            if(temp > 0)

                profit += temp;

        }

        return profit;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

3、旋转数组

给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3

输出: [5,6,7,1,2,3,4]

解释:

向右轮转 1 步: [7,1,2,3,4,5,6]

向右轮转 2 步: [6,7,1,2,3,4,5]

向右轮转 3 步: [5,6,7,1,2,3,4]

示例 2:

输入:nums = [-1,-100,3,99], k = 2

输出:[3,99,-1,-100]

解释:

向右轮转 1 步: [99,-1,-100,3]

向右轮转 2 步: [3,99,-1,-100]

class Solution {

public:

    void rotate(vector<int>& nums, int k) {

        int n = nums.size();

        int temp[n];

        memset(temp,0,sizeof(int)*n);

        k %= n;

        for(int i = 0;i < k;i++){

            temp[i] = nums[n-k+i];

        }

        for(int i = k;i < n;i++){

            temp[i] = nums[i-k];

        }

        for(int i = 0;i < n;i++)

            nums[i] = temp[i];

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

4、给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。

示例 1:

输入:nums = [1,2,3,1]

输出:true

示例 2:

输入:nums = [1,2,3,4]

输出:false

示例 3:

输入:nums = [1,1,1,3,3,4,3,2,4,2]

输出:true

class Solution {

public:

    bool containsDuplicate(vector<int>& nums) {

        sort(nums.begin(),nums.end());

        for(int i = 1;i <nums.size();i++)

        {

            if(nums[i-1] == nums[i])

                return true;

        }

        return false;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

5、只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:

输入: [2,2,1]

输出: 1

示例 2:

输入: [4,1,2,1,2]

输出: 4

class Solution {

public:

    int singleNumber(vector<int>& nums) {

       int len = nums.size(),temp = nums[0];

       if(len == 1)

            return nums[0];

        sort(nums.begin(),nums.end());

        int i = 0;

        while(i < len)

        {

            if(nums[i]!= nums[i+1])

            {

                temp = nums[i];

                break;

            }

            i+=2;

        }

        return temp;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

6、两个数组的交集 II

给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]

输出:[2,2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]

输出:[4,9]

class Solution {

public:

    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {

        vector<int> nums3;

        sort(nums1.begin(),nums1.end());

        sort(nums2.begin(),nums2.end());

        int i = 0 ,j =0,k = 0;

        while((i < nums1.size())&&(j < nums2.size()))

        {

            if(nums1[i] == nums2[j])

            {

                nums3.push_back(nums1[i]);

                i++;

                j++;

            }

            else if(nums1[i] > nums2[j])

            {

                j++;

            }

            else

            {

                i++;

            }

        }

        return nums3;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

7、加一

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:

输入:digits = [1,2,3]

输出:[1,2,4]

解释:输入数组表示数字 123。

示例 2:

输入:digits = [4,3,2,1]

输出:[4,3,2,2]

解释:输入数组表示数字 4321。

示例 3:

输入:digits = [0]

输出:[1]

class Solution {

public:

    vector<int> plusOne(vector<int>& digits) {

        int len = digits.size()-1;

        while(len >= 0)

        {

           

            if(digits[len] == 9)

            {

                digits[len] = 0;

                if(len == 0)

                {

                    digits[len] =1;

                    digits.push_back(0);

                }    

            }

            else

            {

                digits[len] += 1;

                break;

            }

            len--;

        }

        return digits;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

8、移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]

输出: [1,3,12,0,0]

示例 2:

输入: nums = [0]

输出: [0]

class Solution {

public:

    void moveZeroes(vector<int>& nums) {

        int len = nums.size();

        int num = 0;

        for(int i = 0;i < len;i++)

        {

            if(nums[i] == 0)

            {

                num++;

            }

            else

            {

                nums[i-num] =nums[i];

            }

        }

        for(int i=0;i<num;i++)

            nums[len -1-i] = 0;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

9、两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9

输出:[0,1]

解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

输入:nums = [3,2,4], target = 6

输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6

输出:[0,1]

class Solution {

public:

    vector<int> twoSum(vector<int>& nums, int target) {

        vector<int> twonum;

        int temp = nums[0];

        for(int i = 0;i < nums.size()-1;i++)

        {

            temp = target -nums[i];

            for(int j = i+1;j <nums.size();j++)

            {

                if(nums[j] == temp)

                {

                    twonum.push_back(i);

                    twonum.push_back(j);

                    break;

                }

            }

        }

        return twonum;  

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

10、有效的数独

请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。

    数字 1-9 在每一行只能出现一次。

    数字 1-9 在每一列只能出现一次。

    数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

注意:

    一个有效的数独(部分已被填充)不一定是可解的。

    只需要根据以上规则,验证已经填入的数字是否有效即可。

class Solution {

public:

    bool isValidSudoku(vector<vector<char>>& board) {

        int row[9][9]={0},col[9][9]={0},m[9][9]={0};

        for(int i = 0;i < 9;i++)

        {

            for(int j = 0;j < 9;j++)

            {

                if(board[i][j] != '.')

                {

                    int num = board[i][j]-'0'-1;

                    row[i][num]++;

                    col[j][num]++;

                    m[(i/3)+(j/3)*3][num]++;

                    if(row[i][num] == 2 ||col[j][num] ==2 ||m[(i/3)+(j/3)*3][num] == 2)

                    return false;

                }

            }

        }

        return true;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

11、旋转图像

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

class Solution {

public:

    void rotate(vector<vector<int>>& matrix) {

        int len = matrix.size();

        for(int i = 0;i < len/2;i++ )

        {

            int start = i;

            int end = len-i-1;

            for(int j = 0;j < end-start;j++ )

            {

                int temp = matrix[start][start+j];

                matrix[start][start + j] = matrix[end -j][start];

                matrix[end - j][start] = matrix[end][end - j];

                matrix[end][end - j] = matrix[start + j][end];

                matrix[start+j][end] = temp;

            }

        }

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

12、反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

示例 1:

输入:s = ["h","e","l","l","o"]

输出:["o","l","l","e","h"]

示例 2:

输入:s = ["H","a","n","n","a","h"]

输出:["h","a","n","n","a","H"]

class Solution {

public:

    void reverseString(vector<char>& s) {

        int begin = 0;

        int end = s.size()-1;

        int len = end+1;

        for(int i = 0;i <len/2;i++)

        {

            char temp = s[begin + i];

            s[begin + i] = s[end - i];

            s[end -i] = temp;

        }

    }

};

class Solution {

public:

    void reverseString(vector<char>& s) {

        int begin = 0;

        int end = s.size()-1;

        while(begin < end)

        {

            char temp = s[begin];

            s[begin] = s[end];

            s[end] = temp;

            begin++;

            end--;

        }

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

13、整数反转

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。

如果反转后整数超过 32 位的有符号整数的范围 [−231,  231 − 1] ,就返回 0。

假设环境不允许存储 64 位整数(有符号或无符号)。

 231 = 2109863848

示例 1:

输入:x = 123

输出:321

示例 2:

输入:x = -123

输出:-321

示例 3:

输入:x = 120

输出:21

示例 4:

输入:x = 0

输出:0

class Solution {

public:

    int reverse(int x) {

        int temp = 0,ee = 0;          

        while(x)

        {

            ee = x%10;

            if(temp > 214748364 || (temp == 214748364 && ee >7))

                return 0;

            if(temp < -214748364 || (temp == -214748364 && ee < -8))

                return 0;

            temp = temp*10 + ee;

            x=x/10;

        }

        return temp;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

14、字符串中的第一个唯一字符

给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1 。

示例 1:

输入: s = "leetcode"

输出: 0

示例 2:

输入: s = "loveleetcode"

输出: 2

示例 3:

输入: s = "aabb"

输出: -1

class Solution {

public:

    int firstUniqChar(string s) {

        int len = s.size();

        int a[26] = {0},num = 0,ret = -1;

        for(int i = 0 ;i < len ;i ++)

        {

            num = s[i]-'a';

            a[num]++;

        }

        for(int i = 0;i <len;i++)

        {

            num = s[i] -'a';

            if(a[num]== 1)

            {

                ret = i;

                break;

            }      

        }

        return ret;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

15、有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

示例 1:

输入: s = "anagram", t = "nagaram"

输出: true

示例 2:

输入: s = "rat", t = "car"

输出: false

提示:

    1 <= s.length, t.length <= 5 * 104

    s 和 t 仅包含小写字母

class Solution {

public:

    bool isAnagram(string s, string t) {

        int len1 = s.size(),len2 = t.size(),num[2][26] = {0},temp = 0;

        if(len1 != len2)

            return false;

        for(int i = 0;i < len1;i++)

        {

            temp = s[i]-'a';

            num[0][temp]++;

            temp = t[i]-'a';

            num[1][temp]++;

        }

        for(int i = 0;i < 26;i++)

        {

            if(num[0][i] != num[1][i])

                return false;

        }

        return true;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

16、验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。

说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:

输入: "A man, a plan, a canal: Panama"

输出: true

解释:"amanaplanacanalpanama" 是回文串

示例 2:

输入: "race a car"

输出: false

解释:"raceacar" 不是回文串

提示:

    1 <= s.length <= 2 * 105

    字符串 s 由 ASCII 字符组成

class Solution {

public:

    bool isPalindrome(string s) {

        int len = s.size();

        int start = 0,end = len-1,x= 1;

        for(int i = 0;i < len;i++)

        {

            if(s[i]>='a'&&s[i]<= 'z')

            s[i]-=32;

        }

        while(start < end)

        {

           while((start < end)&&!((s[start] >= '0'&& s[start] <= '9')||(s[start] >= 'A')&&(s[start] <= 'Z')))

           {

               start++;

           }

           while((start <end)&&!((s[end]>= '0'&& s[end] <= '9')||(s[end] >= 'A')&&(s[end] <= 'Z')))

           {

               end--;

           }

           if(s[start]!= s[end])

           {

               x = 0;

               break;

           }

           start++;

           end--;

        }

   

        return x;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

17、字符串转换整数 (atoi)

请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。

函数 myAtoi(string s) 的算法如下:

    读入字符串并丢弃无用的前导空格

    检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。

    读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。

    将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。

    如果整数数超过 32 位有符号整数范围 [−231,  231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1 。

    返回整数作为最终结果。

注意:

    本题中的空白字符只包括空格字符 ' ' 。

    除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。

示例 1:

输入:s = "42"

输出:42

解释:加粗的字符串为已经读入的字符,插入符号是当前读取的字符。

第 1 步:"42"(当前没有读入字符,因为没有前导空格)

         ^

第 2 步:"42"(当前没有读入字符,因为这里不存在 '-' 或者 '+')

         ^

第 3 步:"42"(读入 "42")

           ^

解析得到整数 42 。

由于 "42" 在范围 [-231, 231 - 1] 内,最终结果为 42 。

示例 2:

输入:s = "   -42"

输出:-42

解释:

第 1 步:"   -42"(读入前导空格,但忽视掉)

            ^

第 2 步:"   -42"(读入 '-' 字符,所以结果应该是负数)

             ^

第 3 步:"   -42"(读入 "42")

               ^

解析得到整数 -42 。

由于 "-42" 在范围 [-231, 231 - 1] 内,最终结果为 -42 。

示例 3:

输入:s = "4193 with words"

输出:4193

解释:

第 1 步:"4193 with words"(当前没有读入字符,因为没有前导空格)

         ^

第 2 步:"4193 with words"(当前没有读入字符,因为这里不存在 '-' 或者 '+')

         ^

第 3 步:"4193 with words"(读入 "4193";由于下一个字符不是一个数字,所以读入停止)

             ^

解析得到整数 4193 。

由于 "4193" 在范围 [-231, 231 - 1] 内,最终结果为 4193 。

提示:

    0 <= s.length <= 200

    s 由英文字母(大写和小写)、数字(0-9)、' '、'+'、'-' 和 '.' 组成

class Solution {

    public:

    int myAtoi(string s)

    {

            int length = s.size();

            int index = 0;

            while (index < length && s[index] == ' ')

            {

                index++;

            }

            if(index >= length)

            {

                return 0;

            }

            int sign =  1;

            if(s[index] == '-' || s[index] == '+')

            {

                if(s[index] == '-')

                {

                    sign = -1;

                }

                index++;

            }

            int result = 0;

            int temp = 0;

            while (index < length)

            {

                int num = s[index] - '0';

                if(num > 9 || num < 0){

                    break;

                }

                temp = result;

                if((result > 214748364)||((result == 214748364)&&(((sign == 1)&&(num >=7))||((sign == -1)&&(num >=8))) ))

                {

                     if(sign > 0){

                        return 2147483648-1;

                    }else {

                        return -2147483648;

                    }

                }

                result = result * 10 + num;

           

               

                index++;

            }

            return result*sign;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

18、实现 strStr()

实现 strStr() 函数。

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回  -1 。

说明:

当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。

示例 1:

输入:haystack = "hello", needle = "ll"

输出:2

示例 2:

输入:haystack = "aaaaa", needle = "bba"

输出:-1

提示:

    1 <= haystack.length, needle.length <= 104

    haystack 和 needle 仅由小写英文字符组成

class Solution {

public:

    int strStr(string haystack, string needle) {

        int len1 = haystack.size(),len2 = needle.size();

        if(len2 == 0)

            return 0;

        int ret = -1;

        for(int i = 0;i < len1;i++)

        {

            if(haystack[i] == needle[0])

            {

                for(int j = 0;j <len2;j++)

                {

                    if(haystack[i+j] != needle[j])

                    {

                        break;

                    }

                    if(j == (len2-1))

                        return i;

                }

            }

        }

        return ret;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

19、外观数列

给定一个正整数 n ,输出外观数列的第 n 项。

「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。

你可以将其视作是由递归公式定义的数字字符串序列:

    countAndSay(1) = "1"

    countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串。

前五项如下:

1.     1

2.     11

3.     21

4.     1211

5.     111221

第一项是数字 1

描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 "11"

描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 "21"

描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 "1211"

描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 "111221"

要 描述 一个数字字符串,首先要将字符串分割为 最小 数量的组,每个组都由连续的最多 相同字符 组成。然后对于每个组,先描述字符的数量,然后描述字符,形成一个描述组。要将描述转换为数字字符串,先将每组中的字符数量用数字替换,再将所有描述组连接起来。

例如,数字字符串 "3322251" 的描述如下图:

示例 1:

输入:n = 1

输出:"1"

解释:这是一个基本样例。

示例 2:

输入:n = 4

输出:"1211"

解释:

countAndSay(1) = "1"

countAndSay(2) = 读 "1" = 一 个 1 = "11"

countAndSay(3) = 读 "11" = 二 个 1 = "21"

countAndSay(4) = 读 "21" = 一 个 2 + 一 个 1 = "12" + "11" = "1211"


 

提示:

    1 <= n <= 30

class Solution {

public:

    string countAndSay(int n) {

          if(n == 1)

        {

            return "1";

        }

        else

        {

            int cout = 1;

            string str = countAndSay(n-1),result = "";

            for (int i = 0;i < str.size();i++)

            {

                if(str[i] == str[i+1])

                {

                    cout++;

                }

                else

                {

                    result = result + to_string(cout) + str[i];

                    cout = 1;

                }

            }

            return result;

        }

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

20、最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 ""。

示例 1:

输入:strs = ["flower","flow","flight"]

输出:"fl"

示例 2:

输入:strs = ["dog","racecar","car"]

输出:""

解释:输入不存在公共前缀。

提示:

    1 <= strs.length <= 200

    0 <= strs[i].length <= 200

    strs[i] 仅由小写英文字母组成

class Solution {

public:

    string longestCommonPrefix(vector<string>& strs) {

        string ret = "";

        if(strs.size() == 0)

            return ret;

        for(int i = 0;i < strs[0].size();i++)

        {

            char temp = strs[0][i];

            for(int j = 1;j <strs.size();j++)

            {

                if(strs[j][i] != temp)

                {

                    return ret;

                }

            }

            ret += temp;

        }

        return ret;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

21、删除链表中的节点

请编写一个函数,用于 删除单链表中某个特定节点 。在设计函数时需要注意,你无法访问链表的头节点 head ,只能直接访问 要被删除的节点 。

题目数据保证需要删除的节点 不是末尾节点 。

示例 1:

输入:head = [4,5,1,9], node = 5

输出:[4,1,9]

解释:指定链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9

示例 2:

输入:head = [4,5,1,9], node = 1

输出:[4,5,9]

解释:指定链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9

提示:

    链表中节点的数目范围是 [2, 1000]

    -1000 <= Node.val <= 1000

    链表中每个节点的值都是 唯一 的

    需要删除的节点 node 是 链表中的节点 ,且 不是末尾节点

/**

 * Definition for singly-linked list.

 * struct ListNode {

 *     int val;

 *     ListNode *next;

 *     ListNode(int x) : val(x), next(NULL) {}

 * };

 */

class Solution {

public:

    void deleteNode(ListNode* node) {

             node->val = node->next->val;

        node->next = node->next->next;  

       

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

22、删除链表的倒数第N个节点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

示例 1:

输入:head = [1,2,3,4,5], n = 2

输出:[1,2,3,5]

示例 2:

输入:head = [1], n = 1

输出:[]

示例 3:

输入:head = [1,2], n = 1

输出:[1]

提示:

    链表中结点的数目为 sz

    1 <= sz <= 30

    0 <= Node.val <= 100

    1 <= n <= sz

/**

 * 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* removeNthFromEnd(ListNode* head, int n) {

        int len = 0;

        ListNode* temp1 = head;

        ListNode* temp2 = head;

        for(int i = 0;i < n;i++)

            temp2 = temp2->next;

        if(temp2 == 0)

        {

            head = head->next;

            delete temp1;

            return head;

        }

        while(temp2->next != nullptr)

        {

            temp2 = temp2->next;

            temp1 = temp1->next;

        }

        ListNode* deleteNode = temp1->next;

        temp1->next = deleteNode->next;

        delete deleteNode;

        return head;

    }

};


 

/*-------------------------------------------------------------------------------------------------------------------*/

23、反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

class Solution {

public:

    ListNode* reverseList(ListNode* head) {

    ListNode* prev = nullptr;

    ListNode* cur = head;

    while(nullptr != cur)

    {

        ListNode* tmp = cur->next;

        cur->next = prev;

        prev = cur;

        cur = tmp;

    }

    return prev;

    }

};

class Solution {

public:

    ListNode* reverseList(ListNode* head) {

        return reverse(nullptr,head);

    }

    ListNode* reverse(ListNode* prev,ListNode* cur)

    {

        if(cur == nullptr)

            return prev;

        ListNode* tmp = cur->next;

        cur->next = prev;

        return reverse(cur,tmp);

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

24、合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

/**

 * 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* mergeTwoLists(ListNode* list1, ListNode* list2) {

            if(list1 == nullptr)

            return list2;

        if(list2 == nullptr)

            return list1;

        ListNode* dummy = new ListNode(0);

        ListNode* cur = dummy;

        while(list1 != nullptr && list2 != nullptr)

        {

            if(list1->val < list2->val)

            {

                cur->next = list1;

                list1 = list1->next;

            }

            else

            {

                cur->next = list2;

                list2 = list2->next;

            }

            cur = cur->next;

        }

        cur->next = (list1 != nullptr) ? list1: list2;

        return dummy->next;

    }

};

/**

 * 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* mergeTwoLists(ListNode* list1, ListNode* list2) {

            if(list1 == nullptr)

            return list2;

            if(list2 == nullptr)

            return list1;

            if(list1->val <list2->val)

            {

                list1->next = mergeTwoLists(list1->next,list2);

                return list1;

            }

            else

            {

                list2->next= mergeTwoLists(list1,list2->next);

                return list2;

            }

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

25、回文链表

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

/**

 * 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:

    bool isPalindrome(ListNode* head) {

       if(head == NULL) return false;

       vector<int> v;

       ListNode* p = head;

       while(p != NULL){

           v.emplace_back(p->val);

           p = p->next;

       }

       for(int i = 0, j = v.size() - 1; i < j; i++, j--)

           if(v[i] != v[j]) return false;

       return true;

    }

};

/**

 * 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:

    bool isPalindrome(ListNode* head) {

        if(head == NULL) return true;

        ListNode* firstHalfEnd = getHalf(head);  //得到前一半链表的尾结点

        ListNode* secondHalf = reverseList(firstHalfEnd->next); //将后一半链表反转

   

        //判断链表是否回文

        ListNode* p1 = head;

        ListNode* p2 = secondHalf;

        while(p2 != NULL){    //当p2到达尾结点后终止循环,这样可以照顾到链表结点为奇数的情况

            if(p1->val != p2->val) return false;

            p1 = p1->next;

            p2 = p2->next;

        }

        return true;

    }

    //得到前一半部分链表的尾结点

    ListNode* getHalf(ListNode* head){

        ListNode* fast = head;

        ListNode* slow = head;

        while(fast->next != NULL and fast->next->next != NULL){ //注意and两边条件的位置,交换会报错

            fast = fast->next->next;

            slow = slow->next;

        }

        return slow;

    }

    //反转后一半链表(这里使用头插法建立反转后的链表)

    ListNode* reverseList(ListNode* head){

        ListNode* node = NULL;

        ListNode* newHead = NULL;

        ListNode* curr = head;

        while(curr != NULL){

            node = curr;

            curr = curr->next;

            node->next = newHead;

            newHead = node;

        }      

        return newHead;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

26、环形链表

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

/**

 * Definition for singly-linked list.

 * struct ListNode {

 *     int val;

 *     ListNode *next;

 *     ListNode(int x) : val(x), next(NULL) {}

 * };

 */

class Solution {

public:

    bool hasCycle(ListNode *head) {

        if(!head)

        {

            return false;

        }

        ListNode *fast = head;

        ListNode *slow = head;

        while(fast && fast->next)

        {

            slow = slow->next;

            fast = fast->next->next;

            if(slow == fast)

            {

                return true;

            }

        }

        return false;  

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

27、二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例:

给定二叉树 [3,9,20,null,null,15,7],

    3

   / \

  9  20

    /  \

   15   7

返回它的最大深度 3 。

/**

 * 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:

    int maxDepth(TreeNode* root) {

        int max = 1;

        if(root == NULL)

            return 0;

        int leftDepth = maxDepth(root->left);

        int rightDepth = maxDepth(root->right);

        if(leftDepth > rightDepth)

            max += leftDepth;

        else

            max += rightDepth;

        return max;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

28、验证二叉搜索树

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

    节点的左子树只包含 小于 当前节点的数。

    节点的右子树只包含 大于 当前节点的数。

    所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

输入:root = [2,1,3]

输出:true

示例 2:

输入:root = [5,1,4,null,null,3,6]

输出:false

解释:根节点的值是 5 ,但是右子节点的值是 4 。

class Solution {

public:

    bool isValidBST(TreeNode* root) {

        vector<int> res;

        mid_search(root,res);

        for(int i = 0;i <res.size()-1;i++)

            if(res[i]>=res[i+1])

                return false;

        return true;

    }

    void mid_search(TreeNode *root, vector<int> &res)

    {

        if(root == nullptr)

            return ;

        mid_search(root->left,res);

        res.push_back(root->val);

        mid_search(root->right,res);

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

29、对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。

对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。

/**

 * 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:

    bool isSymmetric(TreeNode* root) {

        return func(root->left,root->right);

    }

    bool func(TreeNode* leftTree,TreeNode* rightTree)

    {

        if((leftTree == nullptr && rightTree != nullptr)||(leftTree != nullptr && rightTree == nullptr))

            return false;

        else if(leftTree == nullptr && rightTree == nullptr)

            return true;

        if(leftTree->val != rightTree->val)

            return false;

        return func(leftTree->left,rightTree->right) && func(leftTree->right,rightTree->left);

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

30、二叉树的层序遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

示例 1:

输入:root = [3,9,20,null,null,15,7]

输出:[[3],[9,20],[15,7]]

示例 2:

输入:root = [1]

输出:[[1]]

示例 3:

输入:root = []

输出:[]

/**

 * 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<vector<int>> levelOrder(TreeNode* root) {

        vector<vector<int>> ans;

        if(!root)

            return ans;

        queue<TreeNode*> q;

        q.push(root);

        while(!q.empty())

        {

            vector<int> levelNum;

            int n = q.size();

            for(int i = 0;i < n;i++)

            {

                TreeNode* t = q.front();

                q.pop();

                levelNum.push_back(t->val);

                if(t->left)

                    q.push(t->left);

                if(t->right)

                    q.push(t->right);

            }

            ans.push_back(levelNum);

        }

        return ans;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

31、将有序数组转换为二叉搜索树

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。

高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。

示例 1:

输入:nums = [-10,-3,0,5,9]

输出:[0,-3,9,-10,null,5]

解释:[0,-10,5,null,-3,null,9] 也将被视为正确答案:

示例 2:

输入:nums = [1,3]

输出:[3,1]

解释:[1,null,3] 和 [3,1] 都是高度平衡二叉搜索树。

class Solution {

public:

    TreeNode* sortedArrayToBST(vector<int>& nums) {

        return helper(nums,0,nums.size()-1);

    }

    TreeNode* helper(vector<int>& nums,int left,int right)

    {

        if(left > right)

        {

            return nullptr;

        }

        int mid = (left + right +1)/2;

        TreeNode* root = new TreeNode(nums[mid]);

        root->left = helper(nums,left,mid -1);

        root->right = helper(nums,mid+1,right);

        return root;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

32、合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

示例 1:

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3

输出:[1,2,2,3,5,6]

解释:需要合并 [1,2,3] 和 [2,5,6] 。

合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

示例 2:

输入:nums1 = [1], m = 1, nums2 = [], n = 0

输出:[1]

解释:需要合并 [1] 和 [] 。

合并结果是 [1] 。

示例 3:

输入:nums1 = [0], m = 0, nums2 = [1], n = 1

输出:[1]

解释:需要合并的数组是 [] 和 [1] 。

合并结果是 [1] 。

注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。

 class Solution {

public:

    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {

        if(n==0) return;

        int i = m+n-1;

        for(;i>=0 && m>0 && n>0;--i)

        {

            if(nums1[m-1]<=nums2[n-1])

            {

                nums1[i] = nums2[n-1];

                n--;

            }

            else

            {

                nums1[i] = nums1[m-1];

                m--;

            }

        }

        for(int i=0;i<n;i++){

            nums1[i] = nums2[i];

        }

    }

};

class Solution {

public:

    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {

       int i = m -1;

       int j = n -1;

       int end = n+ m-1;

       while(j >= 0)

       {

           nums1[end--] = (i >= 0 && nums1[i] >nums2[j]) ? nums1[i--]:nums2[j--];

       }

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

33、概述


 

你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

示例 1:

输入:n = 5, bad = 4

输出:4

解释:

调用 isBadVersion(3) -> false

调用 isBadVersion(5) -> true

调用 isBadVersion(4) -> true

所以,4 是第一个错误的版本。

示例 2:

输入:n = 1, bad = 1

输出:1

class Solution {

public:

    int firstBadVersion(int n) {

        int low =1,high = n;

        while(low <high)

        {

            int mid = low +(high -low)/2;

            if(isBadVersion(mid))

            {

                high = mid;

            }

            else

            {

                low = mid + 1;

            }

        }

        return low;

       

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

34、爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

示例 1:

输入:n = 2

输出:2

解释:有两种方法可以爬到楼顶。

1. 1 阶 + 1 阶

2. 2 阶

示例 2:

输入:n = 3

输出:3

解释:有三种方法可以爬到楼顶。

1. 1 阶 + 1 阶 + 1 阶

2. 1 阶 + 2 阶

3. 2 阶 + 1 阶

class Solution {

public:

    int climbStairs(int n) {

        int num[1000] = {0};

        num[1] = 1;

        num[2] = 2;

        for(int i = 3;i <= n;++i)

            num[i] = num[i-1] +num[i -2];

        return num[n];

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

35、买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例 1:

输入:[7,1,5,3,6,4]

输出:5

解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。

     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例 2:

输入:prices = [7,6,4,3,1]

输出:0

解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

class Solution {

public:

    int maxProfit(vector<int>& prices) {

        int min = prices[0],max = 0,temp = 0,len = prices.size();

        for(int i = 0;i < len;i++)

        {

            if(prices[i] < min)

            {

                min = prices[i];

            }

            temp = prices[i]- min;

            if(temp > max)

            {

                max = temp;

            }

        }

        return max;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

36、最大子序和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]

输出:6

解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

输入:nums = [1]

输出:1

示例 3:

输入:nums = [5,4,-1,7,8]

输出:23

提示:

    1 <= nums.length <= 105

    -104 <= nums[i] <= 104

class Solution {

public:

    int maxSubArray(vector<int>& nums) {

        int len = nums.size(),sum = 0,max = nums[0];

        for(int i = 0;i < len;i++)

        {

            sum += nums[i];

            if(sum > max)

                max = sum;

            if(sum < 0)

                sum = 0;

        }

        return max;

    }

};

class Solution {

public:

    int maxSubArray(vector<int>& nums) {

        int len = nums.size(),max = nums[0];

        for(int i = 1;i < len;i++)

        {

            if(nums[i-1]>0)

                nums[i] += nums[i-1];

            if(nums[i] >max)

                max = nums[i];

        }

        return max;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

37、打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

示例 1:

输入:[1,2,3,1]

输出:4

解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。

     偷窃到的最高金额 = 1 + 3 = 4 。

示例 2:

输入:[2,7,9,3,1]

输出:12

解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。

     偷窃到的最高金额 = 2 + 9 + 1 = 12 。

提示:

    1 <= nums.length <= 100

    0 <= nums[i] <= 400

class Solution {

public:

    int rob(vector<int>& nums) {

        int len = nums.size();

        int maxEven = 0,maxOdd = 0;

        for(int i = 0;i < len;i++)

        {

            if(i%2 == 0)

            {

                maxEven += nums[i];

                maxEven = max(maxEven,maxOdd);

            }

            else

            {

                maxOdd += nums[i];

                maxOdd = max(maxEven,maxOdd);

            }

        }

        return max(maxEven,maxOdd);

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

打乱数组

给你一个整数数组 nums ,设计算法来打乱一个没有重复元素的数组。打乱后,数组的所有排列应该是 等可能 的。

实现 Solution class:

    Solution(int[] nums) 使用整数数组 nums 初始化对象

    int[] reset() 重设数组到它的初始状态并返回

    int[] shuffle() 返回数组随机打乱后的结果

示例 1:

输入

["Solution", "shuffle", "reset", "shuffle"]

[[[1, 2, 3]], [], [], []]

输出

[null, [3, 1, 2], [1, 2, 3], [1, 3, 2]]

解释

Solution solution = new Solution([1, 2, 3]);

solution.shuffle();    // 打乱数组 [1,2,3] 并返回结果。任何 [1,2,3]的排列返回的概率应该相同。例如,返回 [3, 1, 2]

solution.reset();      // 重设数组到它的初始状态 [1, 2, 3] 。返回 [1, 2, 3]

solution.shuffle();    // 随机返回数组 [1, 2, 3] 打乱后的结果。例如,返回 [1, 3, 2]

作者:力扣 (LeetCode)

链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xn6gq1/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {

public:

    Solution(vector<int>& nums) {

    }

   

    vector<int> reset() {

    }

   

    vector<int> shuffle() {

    }

};

/**

 * 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();

 */

class Solution {

private:

    vector<int> original;

public:

    Solution(vector<int>& nums) {

        original = nums;

    }

   

    vector<int> reset() {

        return original;

    }

   

    vector<int> shuffle() {

        vector<int> nums(original);                    //用原数组来初始化新数组

        for (int i = nums.size() - 1; ~i; i -- )       //从后往前遍历

        {

            swap(nums[i], nums[rand() % (i + 1)]);     //rand()能随机生成0到最大随机数的任意整数

        }                                              //rand() % (i + 1)能随机生成0到i中的任意整数

        return nums;

    }

};


 

/*-------------------------------------------------------------------------------------------------------------------*/

最小栈

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

    MinStack() 初始化堆栈对象。

    void push(int val) 将元素val推入堆栈。

    void pop() 删除堆栈顶部的元素。

    int top() 获取堆栈顶部的元素。

    int getMin() 获取堆栈中的最小元素。

示例 1:

输入:

["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.

/**

 * Your MinStack object will be instantiated and called as such:

 * MinStack* obj = new MinStack();

 * obj->push(val);

 * obj->pop();

 * int param_3 = obj->top();

 * int param_4 = obj->getMin();

 */


 

class MinStack {

public:

    /** initialize your data structure here. */

    MinStack() {

    }

    void push(int x) {

        left.push(x);

        if (right.empty() || x <= right.top()){

            right.push(x);

        }

    }

    void pop() {

        int top = left.top();  //先让左边出栈并记录元素

        left.pop();        

        if (top == right.top()){  //如果左边出栈得元素等于右边栈顶元素,右边才出

            right.pop();

        }

    }

    int top() {

       

        return left.top();

    }

    int getMin() {

       

        return right.top();

    }

    stack<int> left;  //存正长的数据

    stack<int> right;  //存最小的数据

};


 

/*-------------------------------------------------------------------------------------------------------------------*/

Fizz Buzz

给你一个整数 n ,找出从 1 到 n 各个整数的 Fizz Buzz 表示,并用字符串数组 answer(下标从 1 开始)返回结果,其中:

    answer[i] == "FizzBuzz" 如果 i 同时是 3 和 5 的倍数。

    answer[i] == "Fizz" 如果 i 是 3 的倍数。

    answer[i] == "Buzz" 如果 i 是 5 的倍数。

    answer[i] == i (以字符串形式)如果上述条件全不满足。

示例 1:

输入:n = 3

输出:["1","2","Fizz"]

示例 2:

输入:n = 5

输出:["1","2","Fizz","4","Buzz"]

示例 3:

输入:n = 15

输出:["1","2","Fizz","4","Buzz","Fizz","7","8","Fizz","Buzz","11","Fizz","13","14","FizzBuzz"]

提示:

    1 <= n <= 104



 

作者:力扣 (LeetCode)

链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xngt85/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {

public:

    vector<string> fizzBuzz(int n) {

        vector<string> arr;

        for(int i =1;i <= n;i++)

        {

            string str;

            if(i%3 == 0)

                str+= "Fizz";

            if(i%5 == 0)

                str+= "Buzz";

            if(str.size() == 0)

                str+= to_string(i);

            arr.push_back(str);

        }

        return arr;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

计数质数

给定整数 n ,返回 所有小于非负整数 n 的质数的数量 。

示例 1:

输入:n = 10

输出:4

解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。

示例 2:

输入:n = 0

输出:0

示例 3:

输入:n = 1

输出:0

提示:

    0 <= n <= 5 * 106

作者:力扣 (LeetCode)

链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xnzlu6/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {

public:

    int countPrimes(int n) {

        vector<int> whetherPrime(n,1);

        int ret = 0;

        for(int i = 2;i< n;i++)

        {

            if(whetherPrime[i])

            {

                ret++;

            }

            if((long long)i*i < n)

                for(int j = i*i;j <n;j+=i)

                    whetherPrime[j] = 0;

        }

        return ret;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

3的幂

给定一个整数,写一个函数来判断它是否是 3 的幂次方。如果是,返回 true ;否则,返回 false 。

整数 n 是 3 的幂次方需满足:存在整数 x 使得 n == 3x

示例 1:

输入:n = 27

输出:true

示例 2:

输入:n = 0

输出:false

示例 3:

输入:n = 9

输出:true

示例 4:

输入:n = 45

输出:false

作者:力扣 (LeetCode)

链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xnsdi2/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {

public:

    bool isPowerOfThree(int n) {

       if(n <= 0)

        return false;

        if(1162261467 % n == 0)

            return true;

        return false;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

罗马数字转整数

罗马数字包含以下七种字符: 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:

输入: s = "III"

输出: 3

示例 2:

输入: s = "IV"

输出: 4

示例 3:

输入: s = "IX"

输出: 9

示例 4:

输入: s = "LVIII"

输出: 58

解释: L = 50, V= 5, III = 3.

示例 5:

输入: s = "MCMXCIV"

输出: 1994

解释: M = 1000, CM = 900, XC = 90, IV = 4.

提示:

    1 <= s.length <= 15

    s 仅含字符 ('I', 'V', 'X', 'L', 'C', 'D', 'M')

    题目数据保证 s 是一个有效的罗马数字,且表示整数在范围 [1, 3999] 内

    题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。

    IL 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。

    关于罗马数字的详尽书写规则,可以参考 罗马数字 - Mathematics 。

作者:力扣 (LeetCode)

链接:https://leetcode.cn/leetbook/read/top-interview-questions-easy/xn4n7c/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {

public:

    int val(char s)

    {

        int val = 0;

        switch(s)

        {

            case 'I':val = 1;break;

            case 'V': val = 5; break;

            case 'X': val = 10; break;

            case 'L': val = 50; break;

            case 'C': val = 100; break;

            case 'D': val = 500; break;

            case 'M': val = 1000; break;

        }

        return val;

    }

    int romanToInt(string s) {

        int len = s.size();

        int sun = 0;

        for(int i = 0;i < len-1;i++)

        {

            if(val(s[i]) >= val(s[i+1]))

                sun += val(s[i]);

            else

                sun -= val(s[i]);

        }

        sun += val(s[len-1]);

        return sun;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

位1的个数

编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量)。

提示:

    请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。

    在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在上面的 示例 3 中,输入表示有符号整数 -3。

示例 1:

输入:00000000000000000000000000001011

输出:3

解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。

示例 2:

输入:00000000000000000000000010000000

输出:1

解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。

示例 3:

输入:11111111111111111111111111111101

输出:31

解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。

class Solution {

public:

    int hammingWeight(uint32_t n) {

        int ret = 0;

        for(int i = 0;i < 32;i++)

        {

            if((n&1) == 1)

                ret++;

            n = n>>1;

        }

        return ret;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

汉明距离

两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。

给你两个整数 x 和 y,计算并返回它们之间的汉明距离。

示例 1:

输入:x = 1, y = 4

输出:2

解释:

1   (0 0 0 1)

4   (0 1 0 0)

       ↑   ↑

上面的箭头指出了对应二进制位不同的位置。

示例 2:

输入:x = 3, y = 1

输出:1

class Solution {

public:

    int hammingDistance(int x, int y) {

        int ret = 0;

        int max;

        max = x > y? x:y;

        while(max)

        {

            if((x&1) != (y&1))

                ret++;

            x = x>>1;

            y = y>>1;

            max = max>>1;

        }

        return ret;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

颠倒二进制位

颠倒给定的 32 位无符号整数的二进制位。

提示:

    请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。

    在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在 示例 2 中,输入表示有符号整数 -3,输出表示有符号整数 -1073741825。

示例 1:

输入:n = 00000010100101000001111010011100

输出:964176192 (00111001011110000010100101000000)

解释:输入的二进制串 00000010100101000001111010011100 表示无符号整数 43261596,

     因此返回 964176192,其二进制表示形式为 00111001011110000010100101000000。

示例 2:

输入:n = 11111111111111111111111111111101

输出:3221225471 (10111111111111111111111111111111)

解释:输入的二进制串 11111111111111111111111111111101 表示无符号整数 4294967293,

     因此返回 3221225471 其二进制表示形式为 10111111111111111111111111111111 。

提示:

    输入是一个长度为 32 的二进制字符串


 

class Solution {

public:

    uint32_t reverseBits(uint32_t n) {

        uint32_t ret = 0;

        for(int i = 0;i < 32;i++)

        {

            ret = ret<<1;

            ret += (n&1);

            n = n>>1;

        }

        return ret;

    }

};


 

/*-------------------------------------------------------------------------------------------------------------------*/

杨辉三角

给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

class Solution {

public:

    vector<vector<int>> generate(int numRows) {

        vector<vector<int>> num;

   

        for(int i = 0;i < numRows;i++)

        {

           vector<int>temp(i+1,1);

            for(int j = 1;j < i;j++ )

            {

                temp[j] = num[i -1][j-1] +num[i-1][j];

            }

            num.push_back(temp);

        }

        return num;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

有效的括号

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

    左括号必须用相同类型的右括号闭合。

    左括号必须以正确的顺序闭合。

示例 1:

输入:s = "()"

输出:true

示例 2:

输入:s = "()[]{}"

输出:true

示例 3:

输入:s = "(]"

输出:false

示例 4:

输入:s = "([)]"

输出:false

示例 5:

输入:s = "{[]}"

输出:true


 

class Solution {

public:

    bool isValid(string s) {

        stack<char> str;

        int length = s.size();

        if(length%2 == 1 || s[0] == '}' ||s[0] == ')' || s[0] == ']')

            return false;

        for(int i= 0;i < length;i++)

        {

            if(s[i] == '(' || s[i] == '{' || s[i] == '[')

                str.push(s[i]);

            if(s[i] == ')' || s[i] == '}' || s[i] == ']')

            {

                if(str.empty())

                    return false;

                char temp = str.top();

                str.pop();

                if((temp == '(' && s[i] == ')')||(temp == '{' && s[i] == '}')||(temp == '[' && s[i] == ']'))

                    continue;

                else

                    return false;

            }

        }

        if(!str.empty())

            return false;

        return true;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

缺失数字

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

示例 1:

输入:nums = [3,0,1]

输出:2

解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。

示例 2:

输入:nums = [0,1]

输出:2

解释:n = 2,因为有 2 个数字,所以所有的数字都在范围 [0,2] 内。2 是丢失的数字,因为它没有出现在 nums 中。

示例 3:

输入:nums = [9,6,4,2,3,5,7,0,1]

输出:8

解释:n = 9,因为有 9 个数字,所以所有的数字都在范围 [0,9] 内。8 是丢失的数字,因为它没有出现在 nums 中。

示例 4:

输入:nums = [0]

输出:1

解释:n = 1,因为有 1 个数字,所以所有的数字都在范围 [0,1] 内。1 是丢失的数字,因为它没有出现在 nums 中。

提示:

    n == nums.length

    1 <= n <= 104

    0 <= nums[i] <= n

    nums 中的所有数字都 独一无二

class Solution {

public:

    int missingNumber(vector<int>& nums) {

        int len = nums.size(),temp = nums[0];

        sort(nums.begin(),nums.end());

        for(int i = 0 ;i < len;i++)

        {

            if(nums[i] != i)

            {

                return i;

            }

        }

        return len;

    }

};

/*-------------------------------------------------------------------------------------------------------------------*/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值