【力扣刷题】

文章介绍了两种算法问题的解决方案:在有序二维数组中查找特定整数,采用二分搜索法;搜索可能多次旋转的排序数组,通过二分查找确定分界点。对于旋转数组问题,关键在于识别升序和降序段。最后提到了一个涉及最大连通数的问题,与数组中元素的公因数相关。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

剑指 Offer 04. 二维数组中的查找

题意

在一个二维数组中,每一行都按照从左至右非递减的顺序排序,每一列都按照从上到下非递减的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是由含有该整数。

思路

就是在一个有序的二维数组中,让你快速的找到一个数,如果有就输出true,没有就输出false。
有序!!!!!------->想到了二分
遍历每一行,每一行进行二分,找是否存在这样的数,没有就遍历到下一行。

class Solution
{
public:
	bool findNumberIn2DArray(vector<vector<int>>& vec, int target)
	{
		for (int i = 0; i < vec.size(); i ++)
		{
			int len = vec[i].size();
			for (int j = 0; j < len; j ++)
			{
				int l = 0, r = len - 1;
				while (l < r)
				{
					int mid = l + r >> 1;
					if (vec[i][mid] == target) return true;
					else if (vec[i][mid] < target) l = mid + 1;
					else r = mid;
				}
				if (vec[i][l] == target) return true;
			}
		}
		return false;
	}
};

面试题 10.03. 搜索旋转数组

题意

搜索旋转数组,给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次,次数不不详。请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的。若有多个相同的元素,返回索引值最小的一个。

思路

最开始的时候我没有理解到旋转数组的意思,也没有搞清楚它的规则,试了一下,发现有重复的数,并且有复数,于是我想到了离散化+二分(毕竟实在一个序列中找一个数,优先想到二分,排序嘛),也做出来了 ,但是耗时72ms,太慢了,这里把代码贴出来:

#include <iostream>
class Solution {
public:
    map<int, int> mp;
    int a[100010];

    int search(vector<int>& vec, int target) {
        int cnt = 0;

        for (int i = 0; i < vec.size(); i ++)
        {
            if (!mp.count(vec[i]))
            {
                mp[vec[i]] = i;
                a[cnt ++] = vec[i];
            }
        }

        sort(a, a + cnt);
        for (int i = 0; i < cnt; i ++)
        int l = 0, r = cnt;
        while (l < r)
        {
            int mid = (l + r) >> 1;
            if (a[mid] == target) return mp[a[mid]];
            else if (a[mid] < target) l = mid + 1;
            else r = mid;
        }

        return a[l] == target ? mp[a[l]] : -1;
    }
};

后面重新看了一下样例,发现了规律,每一个排完序后的数组都分为两截,一半是升序,一般是降序,那么,这样就简单了, 首先我们可以找到它的一个分界点,也就是从某个点开始,这个点前面是按照降序,这个点后面是按照升序(当然也有可能是反过来的),然后我们在确定target这个值是在前面这个区间还是后面这个区间,确定了之后我们便可以使用二分了,因为序列是有序的。那么第一步我们就是要确定分解点在哪了,通过后面的样例(有几个没有通过的样例发现的),开头位置和结尾位置可能会有重复,所以我们开始把重复的去掉,然后在用二分,找到第一个比arr[0]大的数,从这个位置是分界点,后面我们再次二分找到答案,所以就是二分+二分

class Solution {
public:
    int search(vector<int>& vec, int target) {
        int l = 0, r = vec.size() - 1;
        while (r > 1 && vec[0] == vec[r]) r --;
        while (l < r)
        {
            int mid = (l + r + 1) >> 1;
            if (vec[mid] >= vec[0]) l = mid;
            else r = mid - 1;
        }
        if (target >= vec[0]) l = 0;
        else l = r + 1, r = vec.size() - 1;
        // 以上是找到分界点

        while (l < r)
        {
            int mid = (l + r) >> 1;
            if (vec[mid] >= target) r = mid;
            else l = mid + 1;
        }

        return vec[r] == target ? r : -1;
    }
};

952. 按公因数计算最大组件大小

题意

一个数组,当两个数的因数大于1的时候,这两个数之间连接一条边,返回其中的最大的连通数。

思路

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值