7月算法训练------第三天(排序)解题报告
题目类型:排序
题目难度:简单
提前记录:
算法时间复杂度分析:
时间复杂度 | 空间复杂度 | |
---|---|---|
选择排序 | O(N^2) | O(1) |
插入排序 | O(N^2) | O(1) |
冒泡排序 | O(N^2) | O(1) |
归并 | O(N*logN) | O(N) |
快排 | O(N*logN) | O(logN) |
堆排 | O(N*logN) | O(1) |
第一题、912. 排序数组
题目链接:912. 排序数组
思路分析:简单的排序算法,主要考察基础
方法一:用Java提供的排序:
代码:
class Solution {
public int[] sortArray(int[] nums) {
Arrays.sort(nums);
return nums;
}
}
方法二:冒泡排序
我们先用冒泡排序试试,结果不能通过,可以看到结果中超出时间限制;还是因为冒泡排序时间复杂度太高了(O(N^2)
)。
class Solution {
public int[] sortArray(int[] nums) {
if(nums.length <= 1){
return nums;
}
for(int end = nums.length - 1; end > 0; end--){
for(int j = 0; j < end; j++){
if(nums[j] > nums[j+1]){
nums[j] = nums[j] ^ nums[j+1];
nums[j+1] = nums[j] ^ nums[j+1];
nums[j] = nums[j] ^ nums[j+1];
}
}
}
return nums;
}
}
方法三:归并排序
我们使用时间复杂度稍低一点的归并排序,时间复杂度为O(N*logN)
。
代码:
class Solution {
private static int[] merge(int[] left, int[] right){
// 结果数组
int[] result = new int[left.length + right.length];
// index:结果数组索引
// i: left 数组索引
// j: right 数组索引
for (int index = 0, i = 0, j = 0; index < result.length; index++){
// 如果left数组遍历结束
if (i >= left.length){
// right数组依次插入result数组,j自增
result[index] = right[j++];
// 如果right数组遍历结束
}else if (j >= right.length){
// left 数组一次插入result数组,i自增
result[index] = left[i++];
}else if (left[i] > right[j]){
// 优先在result数组插入right[j],j自增
result[index] = right[j++];
}else{
// 优先在result数组插入left[i],i自增
result[index] = left[i++];
}
}
return result;
}
public int[] sortArray(int[] source) {
// 数组非空校验和长度校验
if (source == null || source.length < 2){
return source;
}
// 原数组的中间位置
int middle = source.length / 2;
// 原数组前半部分作为一个新数组
int[] left = Arrays.copyOfRange(source, 0, middle);
// 原数组后半部分作为一个新数组
int[] right = Arrays.copyOfRange(source, middle, source.length);
// 递归对left和right数组进行排序
// 二路归并
return merge(sortArray(left), sortArray(right));
}
}
第二题、88. 合并两个有序数组
题目链接:88. 合并两个有序数组
思路分析:
方法一:
将数组二放入数组一中,然后对数组一进行排序。
代码:
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
for(int i = m; i < nums1.length; i++){
nums1[i] = nums2[i - m];
}
Arrays.sort(nums1);
}
}
方法二:插入排序
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
for(int i = m; i < nums1.length; i++){
nums1[i] = nums2[i - m];
}
insertionSort(nums1);
}
public static void insertionSort(int[] arr){
if (arr == null || arr.length < 2){
return;
}
for (int i = 1; i < arr.length; i++){ // 从要插入的数开始
// j>=0控制不发生越界
for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--){
swap(arr, j, j+1);
}
}
}
public static void swap(int[] arr, int i,int j){
//交换arr[i]和arr[j]
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
}
第三题、1037. 有效的回旋镖
题目链接:1037. 有效的回旋镖
思路分析:
首先,我们应该保证三个点不相同:因此,我们应该分别判断三个点时候相等
第二:我们要用线段的两点式来判断三个点是否在一条直线上,我们知道直线的两点式:
y
−
y
1
y
2
−
y
1
=
x
−
x
1
x
2
−
x
1
\frac{y-y_1}{y_2-y_1}=\frac{x-x_1}{x_2-x_1}
y2−y1y−y1=x2−x1x−x1
所以就是用
y
3
y_3
y3来替换
y
y
y,用
x
3
x_3
x3来替换
x
x
x,这样就能判断三点是否在同一条直线上了。
即:
y
3
−
y
1
y
2
−
y
1
=
x
3
−
x
1
x
2
−
x
1
\frac{y_3-y_1}{y_2-y_1}=\frac{x_3-x_1}{x_2-x_1}
y2−y1y3−y1=x2−x1x3−x1
但是,还有个小问题当
y
2
−
y
1
{y_2-y_1}
y2−y1或
x
2
−
x
1
x_2-x_1
x2−x1等于0时,就会有错误;
所以,我们可以稍微改变一下:
(
y
3
−
y
1
)
×
(
x
2
−
x
1
)
=
(
y
2
−
y
1
)
×
(
x
3
−
x
1
)
(y_3-y_1)\times(x_2-x_1)=(y_2-y_1)\times(x_3-x_1)
(y3−y1)×(x2−x1)=(y2−y1)×(x3−x1)
当二者相等时,就返回false
;否则,返回true
。
代码:
class Solution {
public boolean isBoomerang(int[][] points) {
if(points[0][0] == points[1][0] && points[0][1] == points[1][1]){
return false;
}
if(points[0][0] == points[2][0] && points[0][1] == points[2][1]){
return false;
}
if(points[1][0] == points[2][0] && points[1][1] == points[2][1]){
return false;
}
int x = (points[2][1] - points[0][1]) * (points[1][0] - points[0][0]);
int y = (points[2][0] - points[0][0]) * (points[1][1] - points[0][1]);
if(x == y){
return false;
}else{
return true;
}
}
}
第四题、1232. 缀点成线
题目链接:1232. 缀点成线
思路分析:
思路和上一题基本差不多;
先用前两个点确定这条直线,然后将后续每个点代入一个一个试,若有不相等的直接返回false
,若全都满足要求,则返回true
。
代码:
class Solution {
public boolean checkStraightLine(int[][] coordinates) {
for(int i = 2; i < coordinates.length; i++){
int x = (coordinates[i][1] - coordinates[0][1]) * (coordinates[1][0] - coordinates[0][0]);
int y = (coordinates[i][0] - coordinates[0][0]) * (coordinates[1][1] - coordinates[0][1]);
if(x != y){
return false;
}
}
return true;
}
}