刷题记录4

题目1 力扣

编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:

每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int a=matrix.size();
        int b=matrix[0].size();
        int n=a*b-1;
        int L=0,R=n;
        while(L<=R){
            int mid=((R-L)>>1)+L;
            int midRow=mid/matrix[0].size();
            int midCol=mid%matrix[0].size();
            if(matrix[midRow][midCol]>target){
                R=mid-1;
            }else if(matrix[midRow][midCol]<target){
                L=mid+1;
            }else{
                return 1;
            }
        }
        return 0;
    }
};

 二维矩阵可以看作数组的数组,因为整个二维矩阵有序,我们可以直接将其看作一个数组进行二分查找即可。

题目 2力扣

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

class Solution {
public:
    int findMin(vector<int>& nums) {
        int L=0,R=nums.size()-1;
        while(L<=R){
            int mid=((R-L)>>1)+L;
            if(nums[mid]<=nums.back()){
                R=mid-1;
            }else{
                L = mid+1;
            }
        }
        return nums[R+1];
    }
};

题目3 力扣 

峰值元素是指其值严格大于左右相邻值的元素。

给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞ 。

你必须实现时间复杂度为 O(log n) 的算法来解决此问题。

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

简单二分查找出一个峰值即可。

题目4 力扣

给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列  ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。

以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。

你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

你所设计的解决方案必须只使用常量级的额外空间。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        for(int i=0;i<nums.size();++i){
            int L = i+1,R = nums.size()-1;
            while(L<=R){
                int mid = ((R-L)>>1)+L;
                if(nums[mid]==target - nums[i]){
                    return {i+1,mid+1};
                }else if(nums[mid]>target - nums[i]){
                    R = mid - 1;
                }else{
                    L = mid + 1; 
                }
            }
        } 
        return {-1,-1};
    }
};

 固定第一个数,对第二个数进行二分查找。时间复杂度O(NlogN),空间复杂度O(1).

第四题 力扣

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。

你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。

 

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int L = 0,R = nums.size()-1;
        while(L<R){
            int mid = ((R-L)>>1)+L;
            int count = 0;
            for(int n : nums){
                if(n<=mid){
                    count++;
                }
            }
            if(count>mid){
                R = mid;
            }else{
                L = mid + 1;
            }
        } 
        return L;
    }
};

首先遍历一次数组,统计出比中点小的数字的个数count,如果count比中点值大,说明在左半部分,反之在右半部分;重复以上过程即可得到重复的数字的具体情况。

第五题 力扣

给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。

根据维基百科上 h 指数的定义:h 代表“高引用次数”,一名科研人员的 h指数是指他(她)的 (n 篇论文中)总共有 h 篇论文分别被引用了至少 h 次。且其余的 n - h 篇论文每篇被引用次数 不超过 h 次。

如果 h 有多种可能的值,h 指数 是其中最大的那个。

class Solution {
public:
    int hIndex(vector<int>& citations) {
        sort (citations.begin(),citations.end());
        int h = 0,i = citations.size()-1;
        while(i>=0&&citations[i]>h){
            h++;
            i--;
        }
        return h;
    }
};

简单遍历一次使用H计数即可

第六题 力扣

给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数,citations 已经按照 升序排列 。计算并返回该研究者的 h 指数。

h 指数的定义:h 代表“高引用次数”(high citations),一名科研人员的 h 指数是指他(她)的 (n 篇论文中)总共有 h 篇论文分别被引用了至少 h 次。且其余的 n - h 篇论文每篇被引用次数 不超过 h 次。

提示:如果 h 有多种可能的值,h 指数 是其中最大的那个。

请你设计并实现对数时间复杂度的算法解决此问题。

class Solution {
public:
    int hIndex(vector<int>& citations) {
        int n=citations.size();
        int L= 0,R = citations.size()-1;
        while(L<R){
            int mid = ((R - L)>>1)+L;
            if(citations[mid]>=n-mid){
                R = mid;
            }else{
                L= mid +1;
            }
        }
        return citations[R]>=n-R?n-R:0;
    }
};

 相较于上一个题目数字增加了有序的条件,可以使用二分法查找出满足H指数条件的下标,在计算出H指数即可。

题目7 力扣

给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        int n1=nums1.size();
        int n2=nums2.size();
        vector<int> res;
        unordered_set<int> st(nums1.begin(),nums1.end());
        for(int i=0;i<n2;i++){
                if(st.count(nums2[i])){
                    res.push_back(nums2[i]);
                    st.erase(nums2[i]);
                }
            }
        return res;
    }
};

首先创建一个hashmap,将nums1的数字储存进去,然后遍历nums2,如果出现相同的就把这个数字储存进结果数组中。

题目8力扣

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

class Solution {
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
        int n1 =nums1.size();
        int n2 =nums2.size();
        if(n1>n2){
            return intersect(nums2,nums1);
        }
        unordered_map<int,int>m;
        for(int n:nums1){
            ++m[n];
        }
        vector<int>res;
        for(int n:nums2){
            if(m.count(n)){
                res.push_back(n);
                --m[n];
                if(m[n]==0){
                    m.erase(n);
                }
            }  
        }
        return res;
    }
};

 因为这个题目中同一个数字可以出现多次,我们首先创建一个hash数组来储存数字与对应的个数,再遍历nums2,如果找到相同的元素就把这个数储存近结果数组中。

题目9 力扣

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

/**
 * 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* reverseList(ListNode* head) {
        ListNode* pre = nullptr;
        ListNode* cur = head;
        while(cur){
            ListNode*next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
        }
};

 

 

 题目10 力扣

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        ListNode* pre=nullptr;
        ListNode* cur=head;
        while(cur){
            ListNode*next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        vector<int>result;
        if(pre == nullptr){
            return result;
        }
        while(pre){
            result.push_back(pre->val);
            pre = pre->next;
        }
        
        return result;
    }
};

 先反转链表,再把链表中的值提取到数组中,最后打印即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值