算法刷题计划(二)二分查找、兩數相加、无重复字符的的最长子串、寻找两个正序数组的中位数

22 篇文章 0 订阅


(1)二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1


  • 解題思路:

  • 采用二分查找方法,当nums[mid]==target时就返回mid;当nums[mid]>target时低位要mid+1,接着继续判断;当nums[mid]<target时高位要mid-1,接着继续判断;

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int low =0,high=nums.size()-1,mid=0;
        while(low<=high){
            mid=(low+high)>>1;
            if(nums[mid]==target){
                return mid;
            }else if(nums[mid]>target){
                high=mid-1;
            }else{
                low=mid+1;
            }
        }
        return -1;
    }
};

(2)两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:
在这里插入图片描述

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]


  • 解题思路:
  • 先建一个新的链表1,接着将旧的两链表的数值逐段相加,然后又新建链表2为旧的两链表和的取余,链表1与链表2相连,当有需要进位时就给下一次旧的两链表和相加,以此类推直到旧的两链表的指向为空为止。
/**
 * 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* addTwoNumbers(ListNode* l1, ListNode* l2) {
        // ListNode*root = new ListNode(0);
        // ListNode*head=root;
        // int jinwei=0;
        // while(l1!=nullptr||l2!=nullptr||jinwei!=0){
        //     int l1val=l1!=nullptr?l1->val:0;
        //     int l2val=l2!=nullptr?l2->val:0; 
        //     int sumval=l1val+l2val+jinwei;
        //     jinwei=sumval/10;

        //     ListNode*sumNode=new ListNode(sumval%10);
        //     head->next=sumNode;
        //     head=sumNode;
        //     if(l1!=nullptr) l1=l1->next;
        //     if(l2!=nullptr) l2=l2->next;
        // }
        // return root->next;
        ListNode*head=new ListNode(0);
        ListNode*current=head;
        int carry=0;
        while(carry!=0||l1!=nullptr||l2!=nullptr){
            if(l1!=nullptr){
                carry+=l1->val;
                l1=l1->next;
            }
            if(l2!=nullptr){
                carry+=l2->val;
                l2=l2->next;
            }
            current->next=new ListNode(carry%10);
            current=current->next;
            carry/=10;
        }
        return head->next;
    }   
};

(3)无重复字符的最长子串

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

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

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

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

  • 示例 4:
    输入: s = “”
    输出: 0


  • 解题思路:
  • 1)滑动窗口

什么是滑动窗口?

其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列!

如何移动?

我们只要把队列的左边的元素移出就行了,直到满足题目要求!

一直维持这样的队列,找出队列出现最长的长度时候,求出解!

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s.size() == 0) return 0;
        unordered_set<char> lookup;
        int maxStr = 0;
        int left = 0;
        for(int i = 0; i < s.size(); i++){
            while (lookup.find(s[i]) != lookup.end()){
                lookup.erase(s[left]);
                left ++;
            }
            maxStr = max(maxStr,i-left+1);
            lookup.insert(s[i]);
    }
        return maxStr;
        
    }
};

2)利用ascii码解题

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int arr[128];
        for(int i=0;i<128;i++){
            arr[i]=-1;
        }
        int n =s.length();
        int res=0;
        int start=0;
        for(int i=0;i<n;i++){
            int index=char(s[i]);
            start=max(start,arr[index]+1);
            res=max(res,i-start+1);
            arr[index]=i;
        }
        return res;
    }
};

(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

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        if(nums1.size()==0&nums2.size()==1||nums1.size()==1&&nums2.size()==0){
            if(nums1.size()==1&&nums2.size()==0){
                return double(nums1[0]);
            }else if(nums1.size()==0&nums2.size()==1){
                return double(nums2[0]);
            }
        }
        vector<int>sum;
        for(auto a:nums1){
            sum.push_back(a);
        }
        for(auto a:nums2){
            sum.push_back(a);
        }
        sort(sum.begin(),sum.end());
        if(sum.size()%2==1){//单
            cout<<"单"<<endl;
            return double(sum[sum.size()/2]);
        }else{
            cout<<"双"<<endl;
            int totalSum=sum.size()/2;
            return double((sum[totalSum]+sum[totalSum-1]))/double(2);
        }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值