master没听懂,以后再说
一、归并排序
#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
//归并排序算法
void mergeSort(int arr[], int left, int mid, int right)
{
int s[right - left + 1];
int j = 0;
int p1 = left, p2 = mid + 1;
while (p1 <= mid && p2 <= right)//两个子数列还未达到尾部
{
if (arr[p1] <= arr[p2])
{
s[j++] = arr[p1++];
}
else
{
s[j++] = arr[p2++];
}
}
while (p1 <= mid)//其中一个到达尾部后,将另一个数组的剩余部分直接拷贝进s[]数组
{
s[j++] = arr[p1++];
}
while (p2 <= right)
{
s[j++] = arr[p2++];
}
for (int i = 0; i < (right - left + 1); i++)//还给arr[]数组
{
arr[left + i] = s[i];
}
}
void merge(int arr[], int left, int right)//合并主函数,里面有递归
{
if (left < right)//边界条件
{
int mid = (left + right) / 2;
merge(arr, left, mid);
merge(arr, mid + 1, right);
mergeSort(arr, left, mid, right);
}
}
int main()
{
int n = 0;
cin >> n;
int temp = 0;
int arr[100];
for (int i = 0; i < n; i++)
{
cin >>arr[i];
}
merge(arr, 0, n - 1);
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
}
1.1
小和问题
在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组的小和。
例子:[1,3,4,2,5]1左边比1小的数,没有;3左边比3小的数,1;4左边比4小的数,1、3;2左边比2小的数,1;5左边比5小的数,1、3、4、2;所以小和为1+1+3+1+1+3+4+2=16
#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int sum=0;
//归并排序算法
void mergeSort(int arr[], int left, int mid, int right)
{
int s[right - left + 1];
int j = 0;
int p1 = left, p2 = mid + 1;
while (p1 <= mid && p2 <= right)//两个子数列还未达到尾部
{
if (arr[p1] < arr[p2])//这里是易错点,不能用等号,与常规归并排序有一点区别
{
sum+=(right-p2+1)*arr[p1];//小和的关键部分
s[j++] = arr[p1++];
}
else
{
s[j++] = arr[p2++];
}
}
while (p1 <= mid)//其中一个到达尾部后,将另一个数组的剩余部分直接拷贝进s[]数组
{
s[j++] = arr[p1++];
}
while (p2 <= right)
{
s[j++] = arr[p2++];
}
for (int i = 0; i < (right - left + 1); i++)//还给arr[]数组
{
arr[left + i] = s[i];
}
}
void merge(int arr[], int left, int right)//合并主函数,里面有递归
{
if (left < right)//边界条件
{
int mid = (left + right) / 2;
merge(arr, left, mid);
merge(arr, mid + 1, right);
mergeSort(arr, left, mid, right);
}
}
int main()
{
int n = 0;
cin >> n;
int temp = 0;
int arr[100];
for (int i = 0; i < n; i++)
{
cin >>arr[i];
}
merge(arr, 0, n - 1);
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
cout<<sum;
}
1.2
逆序对问题在一个数组中,左边的数如果比右边的数大,则折两个数构成一个逆序对,请打印所有逆序对。
力扣315!!!!!
写了1h没写出来!!!!!!!等水平高了,回头再看这题
二、三指针实现
荷兰国旗问题(用三指针来解决,太妙了)
力扣75:颜色分类
给定一个包含红色、白色和蓝色、共 n
个元素的数组 nums
,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0
、 1
和 2
分别表示红色、白色和蓝色。
必须在不使用库内置的 sort 函数的情况下,且仅使用常数空间的一趟扫描算法解决这个问题。
class Solution {
public:
vector<int> sortColors(vector<int>& nums) {
int i=0;
int j=nums.size()-1;
for(int k=0;k<=j;){
if(nums[k]==0){
swap(nums[i],nums[k]);
i++;
k++;
}else if(nums[k]==1){
k++;
}else{
swap(nums[j],nums[k]);
j--;
}
}
return nums;
}
};