算法题笔记第二周
- 课程目录
- 1、递归基础知识
- 2、冒泡排序基础知识
- 3、选择排序基础知识
- 4、插入排序基础知识
- 5、快速排序基础知识
- 7、归并排序
- 8、剑指offer 40. 最小k个树
- 9、剑指offer 41.数据流中的中位数
- 10、剑指offer 51.数组中的逆序对
- 11、合并k个升序链表
- 12、合并两个有序数组
- 13、颜色分类
- 14、部分排序
- 15、计算右侧小于当前元素个数
- 16、有序数组的平方
- 17、盛最多水的容器
- 18、两数之和
- 19、分发饼干
- 20、柠檬水找零
- 21、用最少数量的箭引爆气球
- 22、移掉k位数字
- 23、跳跃游戏
- 24、摆动序列
- 25、三数之和
- 26、最接近三树之和
- 27、加油站
- 28、合并区间
- li1倒着输出
- li2输出最小公倍数
- li3求字符串的回文子串个数
课程目录
1、递归基础知识
//le-509
class Solution {
public:
int fib(int n) {
if(n==0) return 0;
if(n==1) return 1;
else
return fib(n-1) + fib(n-2) ;
}
};
2、冒泡排序基础知识
O(n2)
#include<iostream>
using namespace std;
void f(int a[], int n){
for(int i=0; i<n-1; i++){
for(int j=0; j<n-i-1; j++){
if(a[j] > a[j+1]){
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp; j+1, 不是j+i,莫写错了
}
}
}
}
void print(int a[], int n){
for(int i=0; i<n; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
int main()
{
int length;
cin >> length;
int i=0;
int a[1000]={0};
while(i < length){
cin >> a[i++];
}
cout << "原数组:"<<endl;
print(a,length);
f(a, length);
cout << "冒泡后:"<<endl;
print(a,length);
return 0;
}
3、选择排序基础知识
O(n2)
#include<iostream>
using namespace std;
void f(int a[], int n){
for(int i=0; i<n-1; i++){
int index = i;
for(int j=i+1; j < n; j++){
if(a[j] < a[index]){
index = j; //index是最小元素的下标
}
}
int temp = a[i];
a[i] = a[index];
a[index] = temp; //每次循环都是把最小元素调到最前面
}
}
void print(int a[], int n){
for(int i=0; i<n; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
int main()
{
int length;
cin >> length;
int i=0;
int a[1000]={0};
while(i < length){
cin >> a[i++];
}
cout << "原数组:"<<endl;
print(a,length);
f(a, length);
cout << "选择排序后:"<<endl;
print(a,length);
return 0;
}
4、插入排序基础知识
O(n2)
5 1 3 4 2
#include<iostream>
using namespace std;
void f(int a[], int n){
for(int i=1; i<n ;i++){
int key = a[i];
int j = i-1;
while(j >= 0 && a[j]>key){
a[j+1] = a[j];
j--;
}
a[j+1] = key;
}
}
void print(int a[], int n){
for(int i=0; i<n; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
int main()
{
int length;
cin >> length;
int i=0;
int a[1000]={0};
while(i < length){
cin >> a[i++];
}
cout << "原数组:"<<endl;
print(a,length);
f(a, length);
cout << "插入排序后:"<<endl;
print(a,length);
return 0;
}
5、快速排序基础知识
#include<iostream>
using namespace std;
int part(int nums[], int left, int right){
int pivot = nums[left];
while(left < right){
while(left<right && nums[right]>pivot){
right--;
}
nums[left] = nums[right];
while(left < right && nums[left] <= pivot){
left++;
}
nums[right] = nums[left];
}
nums[left] = pivot;
return left;
}
void quickSort(int a[], int left, int right){
if(left >= right){
return;
}
int mid = part(a,left,right);
quickSort(a,left,mid-1);
quickSort(a, mid+1, right);
}
void f(int a[], int n){
quickSort(a, 0, n-1);
}
void print(int a[], int n){
for(int i=0; i<n; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
int main()
{
int length;
cin >> length;
int i=0;
int a[1000]={0};
while(i < length){
cin >> a[i++];
}
cout << "原数组:"<<endl;
print(a,length);
f(a, length);
cout << "快速排序后:"<<endl;
print(a,length);
return 0;
}
7、归并排序
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
void print_arr(int arr[], int n){
for(int i=0;i<n;i++){
printf("%d ", arr[i]);
}
putchar('\n');
}
//合并
void merge(int arr[], int tempArr[],int left,int mid,int right){
//标记左半区第一个未排序的元素
int l_pos = left;
//标记右半区第一个未排序的元素
int r_pos = mid+1;
//临时数组元素的下标
int pos = left;
//合并
while(l_pos <= mid && r_pos <= right){
if(arr[l_pos] < arr[r_pos])
tempArr[pos++] = arr[l_pos++];
else
tempArr[pos++] = arr[r_pos++];
}
//合并左半区剩余元素
while(l_pos <= mid)
tempArr[pos++] = arr[l_pos++];
//合并右半区剩余元素
while(r_pos <= right)
tempArr[pos++] = arr[r_pos++];
//把临时组数中合并后的元素复制回原来的数组
while(left <= right){
arr[left] = tempArr[left];
left++;
}
}
void msort(int arr[],int tempArr[],int left, int right){
//如果只有一个元素,就不需要划分
//只有一个元素的区域,本身就是无序的,只需要被归并
if(left < right){
int mid = (left+right)/2;
//递归划分左半区域
msort(arr,tempArr,left,mid);
//递归划分右半区域
msort(arr,tempArr,mid+1,right);
merge(arr, tempArr, left,mid,right);
}
}
void merge_sort(int arr[], int n){
//分配一个辅助数组
int *tempArr = (int *)malloc(n * sizeof(int));
if(tempArr){//辅助数组分配成功
msort(arr,tempArr,0,n-1);
free(tempArr);
}
else{
printf("error: failed to allocate memory");
}
}
int main()
{
int arr[] = {9,5,2,7,12,4,3,1,11};
int n=9;
print_arr(arr,n);
merge_sort(arr, n);
print_arr(arr,n);
return 0;
}
归并排序的课堂版
#include<iostream>
using namespace std;
#include "dayin.hpp"
void merge(int arr[], int reg[], int start,int end)
{
if(start >= end){
return ;
}
int len =end-start, mid = (len>>1) + start;
int start1=start, end1=mid;
int start2 =mid+1, end2 = end;
merge(arr,reg,start1, end1);
merge(arr, reg, start2,end2);
int k = start;
while(start1<=end1 && start2 <= end2)
reg[k++] = arr[start1] < arr[start2] ? arr[start1++]:arr[start2++];
while(start1 <= end1){
reg[k++] = arr[start1++];
}
while(start2 <= end2){
reg[k++] = arr[start2++];
}
for(k=start; k <= end;k++){
arr[k] = reg[k];
cout << " arr[k]"<< arr[k] << " ";
}
cout << endl;
}
int main()
{
int length;
cin >> length;
int i=0;
int a[1000]={0};
while(i < length){
cin >> a[i++];
}
cout << "原数组:"<<endl;
print(a,length);
int reg[10]={0};
merge(a, reg, 0,length-1);
cout << "归并排序后:"<<endl;
print(a,length);
return 0;
}
8、剑指offer 40. 最小k个树
9、剑指offer 41.数据流中的中位数
10、剑指offer 51.数组中的逆序对
11、合并k个升序链表
12、合并两个有序数组
13、颜色分类
14、部分排序
15、计算右侧小于当前元素个数
16、有序数组的平方
17、盛最多水的容器
//le-11
class Solution {
public:
int maxArea(vector<int>& height) {
int res = 0,s;
int left = 0, right = height.size()-1;
while(left < right){
if(height[left] <= height[right]){
s = height[left] * (right-left);
if(s > res) res = s;
left++;
}
else{
s = height[right] * (right-left);
if(s>res) res = s;
right--;
}
}
return res;
}
};
18、两数之和
//le-1
class Solution{
public:
vector<int> twoSum(vector<int> &nums,int target){
unordered_map<int,int> m;
for(int i=0; i < nums.size(); i++){
int t = target - nums[i];
if(m.count(t) == 1){
return vector<int>{m[t],i};
}
m[nums[i]] = i;
}
return vector<int>();
}
};
19、分发饼干
20、柠檬水找零
21、用最少数量的箭引爆气球
22、移掉k位数字
23、跳跃游戏
24、摆动序列
25、三数之和
26、最接近三树之和
27、加油站
28、合并区间
li1倒着输出
输入这种“I love China!”,然后你输出"China! love I",哈哈哈,双相奔赴
#include <cstdio>
#include <cstring>
int main()
{
char a[100] = { "I love China!" };
//char a[100] = { "the"};
int len = strlen(a);
char b[100] = { 0 };
for (int i = len; i >= 0; i--)
{
int j = 0;
while (a[i] != ' '&&i>=0)
{
b[j++] = a[i];
i--;
}
//printf("%s ", b);
for (int k = j; k >= 0; k--)
{
printf("%c", b[k]);
}
printf(" ");
memset(b, 0, sizeof(b));
}
return 0;
}
li2输出最小公倍数
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
int gcd(int a, int b)
{
if (b == 0)
{
return a;
}
return gcd(b, a % b);
}
int main()
{
int a, b;
char c;
while (1)
{
printf("continue or quit: ");
scanf("%c", &c);
if (c == 'Y' || c == 'y')
{
printf("please input two numbers: ");
scanf("%d %d", &a, &b);
printf("%d 和 %d 的最小公倍数是: %d\n", a, b, (a * b) / gcd(a, b));
getchar();
}
else
{
break;
}
}
return 0;
}
li3求字符串的回文子串个数
一开始有点头大,不知道怎么分析,看了网上的例题过后有点思路了,总体就是回文字串长度入手,要么这个回文子串长度是奇数,要么是偶数,奇偶分开,就不会有考虑到判断重复的字符串了。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstring>
int cnt;
void func(int i, int j, int len, char a[])
{
while(i >= 0 && j < len && a[i] == a[j] )
{
cnt++;
i--;
j++;
}
}
int main()
{
char a[100] = { 0 };
scanf("%s", a);
int len = strlen(a);
for (int i = 0; i < len; i++)//从每一个元素开始找,从这个元素为中心,找奇数个子串回文数个数,和偶数个的子串回文数个数
{
func(i,i,len,a);
func(i,i+1,len,a);
}
printf("cnt = %d\n", cnt);
return 0;
}