力扣HOT100

1. 两数之和

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

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

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

示例

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

思路:
采用暴力枚举法时间复杂度为O(n^2),采用哈希表时间复杂度为O(n)。创建的哈希表,key为元素值,value为元素下标。在数组中寻找和为target的两个数,遍历数组元素,当前元素为nums[i],查找数值中是否有存在值为target-nums[i]的元素存在。若存在,则返回哈希表中该元素对应value即下标即当前元素下标i。若不存在,则存入哈希表中。

题解:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
       unordered_map<int, int> hashmap;
       for(int i = 0; i < nums.size(); i++){
           int temp = target - nums[i];
           //查找以temp为key的值
           if(hashmap.find(temp) != hashmap.end()){
               //找到则返回temp下标和该值下标
               return {hashmap[temp], i};
           }
           //未找到则写入哈希表并记录该值下标
           hashmap[nums[i]] = i;
       }
       return {}; 
    }
};


3. 无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

示例 4:

输入: s = ""
输出: 0

思路:
left、right分别记录无重复元素子串的最左最右元素。用哈希表记录无重复子串中的元素。right循环右移,每次判断right指向的元素是否存在哈希表中,即是否是重复元素。若是重复元素,则循环右移left并删除子串中最左元素,直到子串中无重复元素为止。若不是重复元素,则将该元素插入哈希表中。

代码:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        //哈希表记录子串元素
        unordered_set<char> ooc;
        int left = 0, right = 0;//记录子串位置
        int maxlen = 0;
        if(s.size() == 0 )
            return maxlen;
        for(int right = 0; right < s.size(); right++){
            //查找子串中的重复元素逐一删除
            while(ooc.find(s[right]) != ooc.end()){
                ooc.erase(s[left]);
                left++;
            }
            //未重复则插入哈希表
            ooc.insert(s[right]);
            maxlen = max(maxlen, right - left + 1);
        }
        return maxlen;
    }
};


4. 寻找两个正序数组的中位数

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

示例 1:

输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2

示例 2:

输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5

示例 3:

输入:nums1 = [0,0], nums2 = [0,0]
输出:0.00000

示例 4:

输入:nums1 = [], nums2 = [1]
输出:1.00000

示例 5:

输入:nums1 = [2], nums2 = []
输出:2.00000

思路:
若nums1和nums2长度之和为偶数,则中位数为第len/2个数和第len/2+1个数之和的平均值,若为奇数,则中位数为第len/2+1个数。

代码:

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int len1 = nums1.size();
        int len2 = nums2.size();
        int len = len1 + len2;
        int left = 0;
        int right = 0;
        for(int i = 0, j = 0, k = 0; i <= len/2; i++){
            left = right;
            if(j < len1 && (k >= len2 || nums1[j] < nums2[k]) ){
                right = nums1[j++];
            }else{
                right = nums2[k++];
            }
        }
        
        if(len % 2 == 0){
            return (left + right)/2.0;
        }else{
            return right;
        }

    }
};


5. 最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd"
输出:"bb"

示例 3:

输入:s = "a"
输出:"a"

示例 4:

输入:s = "ac"
输出:"a"

思路:
长度为1的子串都是回文,长度为2的子串若元素相等是回文。长度为3即right-left<3时左右元素相等即是回文。其他情况,判断最左元素s[left]与最右元素s[right]是否相等,相等且s[left-1,right+1]的子串是回文则s[left, right]也是回文。

代码:

class Solution {
public:
    string longestPalindrome(string s) {
        if(s.length() == 1 ||(s.length() == 2 && s[0] == s[1])){
            return s;
        }
   
        //子串左右位置
        int left = 0, right = 0;
        int len = s.length();
        //记录最长子串长度,初始为1
        int maxLen = 1;
        //记录最长子串开始位置
        int maxStrBegin = 0;
        //dp[left][right]值为1表示 以left开头 right结尾的子串是回文子串
        vector<vector <int> > dp(len, vector<int> (len));
        //初始化,单个元素都为长度为1的回文子串
        for(int i = 0; i < len; i++){
            dp[i][i] = 1;
        }
        //枚举子串长度
        for(int i = 2; i <= len; i++){
            //枚举子串起始位置
            for(int left = 0; left < len; left++){
                int right = left + i -1;
                if(right >= len){
                    break;
                }
                //若左边元素不等于右边元素则不是回文
                if(s[left] != s[right]){
                    dp[left][right] = 0;
                }else{
                    //长度为3的情况 左右相等是回文
                    if(right - left < 3){
                        dp[left][right] = 1;
                    }else{
                        dp[left][right] = dp[left + 1][right - 1];
                    }
                }
                //是回文且长度大于当前记录的最大值,则更新
                if(dp[left][right] == 1 && right - left + 1 > maxLen){
                    maxLen = right - left + 1;
                    maxStrBegin = left;
                }
            }
        }
        return s.substr(maxStrBegin, maxLen); 
    }
};


6. Z字形变换

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:

P   A   H   N
A P L S I I G
Y   I   R

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。

请你实现这个将字符串进行指定行数变换的函数:

string convert(string s, int numRows);

示例 1:

输入:s = "PAYPALISHIRING", numRows = 3
输出:"PAHNAPLSIIGYIR"

示例 2:

输入:s = "PAYPALISHIRING", numRows = 4
输出:"PINALSIGYAHRPI"

解释:

P     I    N
A   L S  I G
Y A   H R
P     I

示例 3:

输入:s = "A", numRows = 1
输出:"A"

思路:
按Z字形填充,可理解为从第0行开始向下填充至第numRows - 1行为止,然后斜向上填充至第0行。所以在第0行和第numRows - 1行时需改变填充方向。向下填充时行数依次加1,向上填充时行数依次减1。由此将每个元素从左到右填入相应的行,各行拼接得到的字符串即为转换后的字符串。

代码:

class Solution {
public:
    string convert(string s, int numRows) {
        if(numRows == 1){
            return s;
        }

        vector<string> rows(min(numRows, (int)s.size()));
        int curRow = 0;
        //填充方向
        bool goingDown = false;

        for(char c : s){
            rows[curRow] += c;
            //若在第一行或最后一行需更换方向
            //第一行goingDown为true,最后一行goingDown为false
            if(curRow == 0 || curRow == numRows - 1){
                goingDown = !goingDown;
            }
            //在第一行row加1 最后一行row-1
            curRow +=  goingDown ? 1 : -1;
        }
        string ans;
        for(string row : rows){
            ans += row;
        }
        return ans;
    }
    
};


7. 整数反转

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

如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。

示例 1:

输入:x = 123
输出:321

示例 2:

输入:x = -123
输出:-321

示例 3:

输入:x = 120
输出:21

示例 4:

输入:x = 0
输出:0

代码:

class Solution {
public:
    int reverse(int x) {
        int num = 0;
        while( x != 0){
            if (num < INT_MIN/10 || num > INT_MAX/10) {
                return 0;
            }
            int digit = x % 10;
            x = x/10;
            num = num*10 +  digit;
        }
        return num;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值