力扣-240+CCF 202006-2 稀疏向量+202006-1 线性分类器

题目一

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路

这个题目看起来很简单,最暴力的解法无非就是访问矩阵的每一个点即可,但这效率不高,所以在提及检索的时候,我们第一个想到的就是二分检索(一维),所以我们从这里出发,一起看本题要用什么方法。

方法一:一个维度的二分检索,另一个维度顺序

1、这个是我自己想的思路,很简单,二维矩阵的每一行都是一个一维数组,那么我们可不可以简化每一行的检索过程,即每一行上进行快速的二分检索,这一行没有就进入下一行,这样就可以找到答案。
2、值得注意的是,当进入新的一行的时候,发现行首的值大于目标值,根据题意可知,从该行起,他的下面所有元素都大于目标,就没必要找了,减少搜索过程。

方法二:二维二分查找

二维最大的特点就是,有两个维度,所以二分找的时候不能只找一个维度,必须找一次,搜索两个维度,为了做到这点,其实也很简单,只需要沿着对角线搜索就行。

在这里插入图片描述
过程如上图所示,按照对角线搜索即可,但也如图所示,会产生很多冗余查找,所以时间复杂度较高。

方法三:线性复杂度查找

以上方法其实都没充分用到本体的关键性条件,即每行从左到右递增,每列从上到下递减。
1、首先要明白这个矩阵里的每个元素其实都是有序的
2、第二,我们要找到边界关键点,即他在边界且可进可退,如果目标大于或者小于这个节点,那么都得能找出相应的移动方向,所以关键点初始点只能是左下角,右上角
3、从关键点走,以左下角为例,小于关键点,则关键点就往上走,反之向右走,直到找到目标或者向上向右越界

代码

方法一代码:

注:在使用vector或者数组的时候,一定注意,他的有效范围在0~n-1,千万别越界。

class Solution {
    
    
public:
	bool binaryFind(int target, vector<int>& item) {
    
    //二分查找,不做赘述
		int i = 0, j = item.size() - 1;
		while (i <= j) {
    
    
			int mid = (i + j) / 2;
			if (item[mid] == target) {
    
    
				return true;
			}
			else if(item[mid] > target){
    
    
				j = mid - 1;
			}
			else if (item[mid] < target) {
    
    
				i = mid + 1;
			}
		}
		return false;
	}
	bool searchMatrix(vector<vector<int>>& matrix, int target) {
    
    

		int m = matrix.size();
		int n = matrix[0].size();

		if (target<matrix[0][0] || target>matrix[m - 1][n - 1]) {
    
    //把很明显不对的数据排除
			return false;
		}

		if (target == matrix[0][0] || target == matrix[m - 1][n - 1]) {
    
    
			return true;
		}

		for (int i = 0; i < matrix.size(); i++) {
    
    //枚举行
			if (matrix[i][0] > target) {
    
    
				break;
			}
			if (binaryFind(target, matrix[i])) {
    
    
				return true;
			}
		}
		return false;
	}
};

(所有代码均已在力扣上运行无误)

经测试,该代码运行情况是(经过多次测试所得最短时间):

在这里插入图片描述

时间复杂度:O(nlgn)
空间复杂度:O(1)

方法二代码:

class Solution {
    
    
public:
	int m, n;
	bool binaryFind(vector<vector<int>>& matrix, int target, int p, bool col_or_row) {
    
    //二维二分查找
		int i = 0;
		int j = col_or_row ? m - 1 : n - 1;//为真查列,为假查行
		if (col_or_row) {
    
    //col_or_row决定查列还是行
			while (i <= j) {
    
    //二分查列
				int mid = (i + j) / 2;
				if (matrix[mid][p] == target) {
    
    
					return true;
				}
				else if (matrix[mid][p] > target) {
    
    
					j = mid - 1;
				}
				else if (matrix[mid][p] < target) {
    
    
					i = mid + 1;
				}
			}
		}
		else {
    
    
			while (i <= j) {
    
    //二分查行
				int mid = (i + j) / 2;
				if (matrix[p][mid] == target) {
    
    
					return true;
				}
				else if (matrix[p][mid] > target) {
    
    
					j = mid - 1;
				}
				else if (matrix[p][mid] < target) {
    
    
					i = mid + 1;
				}
			}
		}
		return false;
	}
	bool searchMatrix(vector<vector<int>>& matrix, int target) {
    
    

		m = matrix.size();
		n = matrix[0].size();

		if (matrix.empty() || matrix[0].empty()) {
    
    //处理特殊情况,为空,两种空的情况
			return false;
		}

		if (target<matrix[0][0] || target>matrix[m - 1][n - 1]) {
    
    //排除肯定错的
			return false;
		}

		if (target == matrix[0][0] || target == matrix[m - 1][n - 1]) {
    
    
			return true;
		}

		int shorterDim = min(matrix.size(), matrix[0].size());//找对角线
		
		for (int i = 0; i < shorterDim; i++) {
    
    //按照对角线找点
			bool find1 = binaryFind(matrix, target, i, true);//扫列
			bool find2 = binaryFind(matrix, target, i, false);//扫行
			if (find1 || find2) {
    
    
				return true;
			}
		}
		return false;
	}
};

(所有代码均已在力扣上运行无误)

经测试,该代码运行情况是(经过多次测试所得最短时间):
在这里插入图片描述
在这里插入图片描述

方法三代码:

1、左下角

class Solution {
    
    
public:
	bool searchMatrix(vector<vector<int>>& matrix, int target) {
    
    
		int m = matrix.size() - 1, n = 0;//初始值
		while (m >= 0 && n < matrix[0].size()) {
    
    //越界条件
			if (matrix[m][n] > target) {
    
    
				m--;
			}
			else if (matrix[m][n] < target) {
    
    
				n++;
			}
			else {
    
    
				return true;
			}
		}
		return false;
	}
};

2、右上角

class Solution {
    
    
public:
	bool searchMatrix(vector<vector<int>>& matrix, int target) {
    
    
		int m = 0, n = matrix[0].size() - 1;
		while (m < matrix.size() && n >= 0) {
    
    
			if (matrix[m][n] > target) {
    
    
				n--;
			}
			else if (matrix[m][n] < target) {
    
    
				m++;
			}
			else {
    
    
				return true;
			}
		}
		return false;
	}
};

(所有代码均已在力扣上运行无误)

经测试,该代码运行情况是(经过多次测试所得最短时间):
在这里插入图片描述
在这里插入图片描述

题目二:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

思路

直接模拟题目要求,注意输出的时候一定要换行

代码

///202006-1	线性分类器

#include <iostream>
#include <algorithm>
#include <unordered_set>
using namespace std;

int n, m;
int t0, t1, t2;

struct point {
    
    //点
	int x;
	int y;
};

point p_A[1005], p_B[1005];//AB类型的点

int main()
{
    
    
	cin >> n >> m;
	int cnt_A = 0, cnt_B = 0;//AB类点的个数
	for (int i = 0; i < n; i++) {
    
    
		int tmp_x, tmp_y;
		char tmp_c;
		scanf("%d %d %c", &tmp_x, &tmp_y, &tmp_c);//输入
		if (tmp_c == 'A') {
    
    //输入
			p_A[cnt_A].x = tmp_x;
			p_A[cnt_A].y = tmp_y;
			cnt_A++;
		}
		else {
    
    
			p_B[cnt_B].x = tmp_x;
			p_B[cnt_B].y = tmp_y;
			cnt_B++;
		}
	}
	for (int i = 0; i < m; i++) {
    
    //开始处理不同直线
		cin >> t0 >> t1 >> t2;
		int change = -1;
		bool fal = false;
		for (int j = 0; j < cnt_A; j++) {
    
    //处理A类点
			int tmp = p_A[j].x*t1 + p_A[j].y*t2;
			if (j == 0) {
    
    //第一个点决定所有的点与直线的相对位置
				if (tmp + t0 < 0) {
    
    
					change = -1;
				}
				else {
    
    
					change = 1;
				}
			}
			else {
    
    
				if( (tmp + t0 < 0&&change==1) || (tmp + t0 > 0 && change == -1)){
    
    
					fal = true;//因为出现了在直线不同位置的点,代表A类点出现在直线两侧
					break;
				}
			}
		}
		if (!fal) {
    
    //处理B类点
			for (int j = 0; j < cnt_B; j++) {
    
    //含义同上
				int tmp = p_B[j].x*t1 + p_B[j].y*t2;
				if (j == 0) {
    
    
					if (tmp + t0 < 0) {
    
    
						change = -1;
					}
					else {
    
    
						change = 1;
					}
				}
				else {
    
    
					if ((tmp + t0 < 0 && change == 1) || (tmp + t0 > 0 && change == -1)) {
    
    
						fal = true;
						break;
					}
				}
			}
		}
		if (fal) {
    
    
			printf("%s\n", "No");
		}
		else {
    
    
			printf("%s\n", "Yes");
		}
	}
}

(所有代码均已在力扣上运行无误)

经测试,该代码运行情况是(经过多次测试所得最短时间):

在这里插入图片描述

时间复杂度:O(N^2)

题目三

在这里插入图片描述
在这里插入图片描述

思路:

这个题其实思路很简单,但是需要处理好大数据的问题,所以基础思路就是哈希。思路就是以一个向量作为主体,第二个向量边读取,边查找第一个向量想同纬度的值。

代码:

注意:为了防止越界,一定要用long long,做题之前看好数据规模约定!!!!!!

//202006-2	稀疏向量

#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;

long long n, a, b;

int main()
{
    
    
	cin >> n >> a >> b;
	long long ans = 0;
	unordered_map<long long, long long> item;//哈希实现的map
	for (long long i = 0; i < a; i++) {
    
    
		long long x, y;
		scanf("%lld%lld", &x, &y);
		item.insert(pair<long long, long long>(x, y));//添加map
	}
	for (long long i = 0; i < b; i++) {
    
    
		long long x, y;
		scanf("%lld%lld", &x, &y);
		if (item.count(x) == 0) {
    
    //同纬度没查到,则意味着同纬度下第一个向量的值为0
			continue;
		}
		else {
    
    
			ans += item.at(x)*y;
		}
	}
	cout << ans;
}

(所有代码均已在力扣上运行无误)

经测试,该代码运行情况是(经过多次测试所得最短时间):
在这里插入图片描述

时间复杂度:O(N)

猜你喜欢

转载自blog.csdn.net/qq_45678698/article/details/120292567