1232缀点成线
解题思路
通过画图可以看出,只要任意一点和其他所有点连线不在一条直线上,即可return false;
其次,为了判断何时直线平行与y轴,进行了flag标记,只有flag相同且k相同才可以返回true;反之就会返回false;
因为只有这种情况无法计算k值(分母为0)
代码
class Solution {
public:
bool checkStraightLine(vector<vector<int>>& coordinates) {
//只需要任意一个点和其他所有点建立连线的斜率都相等,就可以满足,反之return false;
int x0 = coordinates[0][0];
int y0 = coordinates[0][1];
double k0 = 0;double k1 = 0;int flag0 = 0;int flag1 = 0;
if(coordinates[1][0] - x0 == 0){
//此时用k来记录到y轴的距离;
k0 = x0;flag0 = 1;
}else{
k0 = (coordinates[1][1] - y0)* 1.0 / (coordinates[1][0] - x0);
}
for(int i = 2;i<coordinates.size();i++){
flag1 = 0;
if(coordinates[i][0] - x0 == 0){
//此时用k来记录到y轴的距离;
k1 = x0;flag1 = 1;
}else{
k1 = (coordinates[i][1] - y0)* 1.0 / (coordinates[i][0] - x0);
}
if(k1 != k0||flag0 != flag1)return false;
}
return true;
}
};
1037有效的回旋镖
解题思路
注意是:不在一条直线上 才返回true;
//其实可以不用 判断是否有重复的点,因为只要 有重复的点,那么这三个点必定在同一条直线上。
题中先判断是否有重复的点,经过筛选后,就没有重复的点了。
如果0,1两点x不等,那么就直接计算k0,如果1,2x相等,那么必定不在一条直线上(因为1,2的y必定不等)
如果0,1两点x相等,那么直接看0,2两点x是否相等,如果不等 ,那么必定 不在一条直线上。return true;反之相等 return false;
代码
class Solution {
public:
bool isBoomerang(vector<vector<int>>& point) {
/*
直接判断是否都在一条直线上就行。
两点构成一条直线,所以计算任意两条直线的斜率K即可.
为了避免有重复的点,可以选择计算所有任意两个点的斜率。
*/
if(point[0][0] == point[1][0]&&point[0][1] == point[1][1]){
return false;
}else if(point[0][0] == point[2][0]&&point[0][1] == point[2][1]){
return false;
}else if(point[1][0] == point[2][0]&&point[1][1] == point[2][1]){
return false;
}
double k1 = 0;
double k2 = 0;
if(point[0][0]-point[1][0]!=0){
k1 = (point[0][1] - point[1][1])* 1.0/(point[0][0]-point[1][0]);
if(point[0][0]-point[2][0]!=0){
k2 = (point[0][1] - point[2][1]) * 1.0/(point[0][0]-point[2][0]);
if(k1 == k2)return false;
else return true;
}else{
return true;
}
}
else{
k1 = point[0][0];
if(point[1][0]-point[2][0]!=0){
return true;
}else{
return false;
}
}
}
};
88合并两个有序数组
解题思路
因为直接在nums1数组上进行比较会不断使其内的数向后移动,浪费时间。
所以放在第三个数组中,最终再依次赋值回去。
在while循环中只有s1,s2都遍历结束后再退出循环即可。
代码
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
/*
1.建立两个指针,nums1一定最长,如果时s2遍历完了,那么直接返回即可。
*/
int sorted[n+m];
int cur;
int p1 = 0;int p2 = 0;
while(p1<m || p2<n){
if(p1 == m){
cur = nums2[p2++];
}else if(p2 == n){
cur = nums1[p1++];
}else if(nums1[p1] < nums2[p2]){
cur = nums1[p1++];
}else{
cur = nums2[p2++];
}
sorted[p1 + p2 -1] = cur;//每次最多有一个加一(要么p1++,要么p2++)
}
for(int i = 0;i!=m + n;i++){
nums1[i] = sorted[i];
}
}
};
912排序树组
解题思路
每次在randomized_partition中挑选一个主元并且会在此函数内调用partition函数进行左右分类。
(要知道,randomized_partition函数调用结束后,只会得到为主元左侧皆小于等于主元,右侧皆大于主元的序列,并没对两侧的序列进行排序)。所以要不断地进入左侧,和右侧进行randomized_partition函数的调用,因为,我们需要再选一个主元,然后再根据其值在左右两侧进行分类。直到,选完某个主元后,其左侧或者右侧都最多只有 1个元素,那么就可以是一个完整的排序完毕的小序列了,再依次返回即可。
代码
class Solution {
public:
int partition(vector<int>&nums,int l, int r){
int pivot = nums[r];
int i = l - 1;//为什么i 要 - 1,为了方便一会循环中的修改。
//即i始终是小于等于主元的那些数中最右边的那个。
for(int j = l;j <= r - 1;j++){
if(nums[j] <= pivot){
i = i + 1;
swap(nums[i],nums[j]);
}
}
//最后将主元和大于主元的数中最小的那个进行交换.
swap(nums[i + 1],nums[r]);
return i + 1;
}
int randomized_partition(vector<int>& nums,int l ,int r){
int i = rand() % (r - l + 1) + l;//随机选取作为主元。
swap(nums[r],nums[i]);//将选中的主元放置在数组最末。
return partition(nums,l,r);
}
void randomized_quicksort(vector<int>& nums,int l ,int r){
if(l < r){
int pos = randomized_partition(nums,l,r);
randomized_quicksort(nums,l, pos - 1);
randomized_quicksort(nums,pos + 1,r);
}
}
vector<int> sortArray(vector<int>& nums) {
srand((unsigned)time(NULL));//啥意思
randomized_quicksort(nums,0,(int)nums.size()-1);
return nums;
}
};