【力扣刷题】

剑指 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的时候,这两个数之间连接一条边,返回其中的最大的连通数。

思路

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于力扣刷题C++常用操作,我可以给你一些常见的操作和技巧: 1. 使用 STL 容器和算法库:STL(Standard Template Library)是 C++ 标准库中的一个重要组成部分,包含了许多常用的容器和算法。在力扣刷题中,使用 STL 可以大大提高代码的效率和可读性。例如,vector 可以用来存储动态数组,sort 可以用来排序等等。 2. 使用 auto 关键字:auto 关键字可以自动推导变量类型,可以减少代码量和提高可读性。例如,auto x = 1; 可以自动推导出 x 的类型为 int。 3. 使用 lambda 表达式:lambda 表达式是 C++11 中引入的一种匿名函数,可以方便地定义一些简单的函数对象。在力扣刷题中,使用 lambda 表达式可以简化代码,例如在 sort 函数中自定义比较函数。 4. 使用位运算:位运算是一种高效的运算方式,在力扣刷题中经常会用到。例如,左移运算符 << 可以用来计算 2 的幂次方,右移运算符 >> 可以用来除以 2 等等。 5. 使用递归:递归是一种常见的算法思想,在力扣刷题中也经常会用到。例如,二叉树的遍历、链表的反转等等。 6. 使用 STL 中的 priority_queue:priority_queue 是 STL 中的一个容器,可以用来实现堆。在力扣刷题中,使用 priority_queue 可以方便地实现一些需要维护最大值或最小值的算法。 7. 使用 STL 中的 unordered_map:unordered_map 是 STL 中的一个容器,可以用来实现哈希表。在力扣刷题中,使用 unordered_map 可以方便地实现一些需要快速查找和插入的算法。 8. 使用 STL 中的 string:string 是 STL 中的一个容器,可以用来存储字符串。在力扣刷题中,使用 string 可以方便地处理字符串相关的问题。 9. 注意边界条件:在力扣刷题中,边界条件往往是解决问题的关键。需要仔细分析题目,考虑各种边界情况,避免出现错误。 10. 注意时间复杂度:在力扣刷题中,时间复杂度往往是评判代码优劣的重要指标。需要仔细分析算法的时间复杂度,并尽可能优化代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值