【1】有序数组中的和因子
/**
有序数组中找和的因子,即打印所有相加为K的数对
头尾双指针法
*/
void SumK(int A[], int N, int K){
int left = 0;
int right = N-1;
int sum;
while(left < right){
sum = A[left] + A[right];
if(sum < K){
left++;
}else if(sum > K){
right--;
}else{
cout<<"("<<A[left]<<","<<A[right]<<")"<<endl;
left ++;
}
}
}
【2】需要排序的最短子数组
/**需要排序的最短子数组
这个题没有套路:只适用于升序
降序的需要后续再思考一下,找到升序与降序两个不同角度中最短的数组输出
*/
int findSegment(int A[], int n){
int p1 = -1, p2 = -1;//待排序的左边界,升序
int p1d = -1, p2d = -1;//待排序的右边界
int max = A[0];
int min = A[n-1];
int i = 0;
//拓展右端点:更新历史最高,只要右侧出现比历史最高低的,就应该将右边界扩展到此处
for(i=0; i<n; i++){
// if((i < n-1) && (A[i] > A[i+1]) && (p1 == -1))
// p1 = i;
if(A[i] > max)
max = A[i];
//只要低于历史高峰,就要扩展排序区间的右端点
if(A[i] < max)
p2 = i;
}
//找左端点:更新历史最低,只要左侧额出现比历史最低高的,就应该将左边界扩展到此处
for(i=n-1; i>=0; i--){
if(A[i] < min){
min = A[i];
}
if(A[i] > min)
p1 = i;
}
if(p1 == -1){
cout <<"[0,0]"<<endl;
return 0;
}
else{
cout<<"["<<p1<<"," <<p2<<"]"<<endl;
return (p2-p1+1);
}
}
【3】topK
#include <iostream>
#include <iomanip>
using namespace std;
#define MAX 10000
/*小根堆排序*/
void MinHeapFixDown(int A[], int i, int n){//A是待排序数组,i是待调整节点
//找到左右孩子
int left = 2 * i + 1;
int right = 2 * i + 2;
if(left >= n){//如果左孩子越界(不存在),那么i就是叶子节点,不用继续了
return ;
}
int min = left;
if(right >= n){
min = left;//右孩子越界(不存在),那么最小值就是左孩子
}
else{//左右孩子都存在,较小者为min
if(A[right] < A[left])
min = right;
}
//此时min就指向了左右孩子中较小的那个
//如果A[i]比两个孩子都要小,不用调整
if(A[i] <= A[min])
return;
//否则,找到两个孩子中较小的,和i交换
int temp = A[i];
A[i] = A[min];
A[min] = temp;
//小孩子那个位置的值发生了变化,i变更为小孩子那个位置,递归调整(由于发生了位置变换,所以要继续调整保证变换后堆的性质依旧成立)
MinHeapFixDown(A,min,n);
}
void MinHeap(int A[], int n){//堆化
for(int i=(n/2-1); i>=0; i--){
MinHeapFixDown(A,i,n-1);
}
}
/*大根堆排序*/
void MaxHeapFixDown(int A[], int i, int n){//A是待排序数组,i是待调整节点
//找到左右孩子
int left = 2 * i + 1;
int right = 2 * i + 2;
if(left >= n){//如果左孩子越界(不存在),那么i就是叶子节点,不用继续了
return ;
}
int max = left;
if(right >= n){
max = left;//右孩子越界(不存在),那么最大值就是左孩子
}
else{//左右孩子都存在,较大者为max
if(A[right] > A[left])
max = right;
}
//此时max就指向了左右孩子中较大的那个
//如果A[i]比两个孩子都要大,不用调整
if(A[i] >= A[max])
return;
//否则,找到两个孩子中较大的,和i交换
int temp = A[i];
A[i] = A[max];
A[max] = temp;
//大孩子那个位置的值发生了变化,i变更为大孩子那个位置,递归调整(由于发生了位置变换,所以要继续调整保证变换后堆的性质依旧成立)
MaxHeapFixDown(A,max,n);
}
void MaxHeap(int A[], int n){//堆化
for(int i=(n/2-1); i>=0; i--){
MaxHeapFixDown(A,i,n-1);
}
}
/**
* 求海量数据(正整数)按逆序排列的前k个数(topK),因为数据量太大,不能全部存储在内存中,只能一个一个地从磁盘或者网络上读取数据,
* 请设计一个高效的算法来解决这个问题
第一行:用户输入K,代表要求得topK
随后的N(不限制)行,每一行是一个整数代表用户输入的数据
用户输入-1代表输入终止
请输出topK,从小到大,空格分割
*/
int heap[MAX];
int index = 0;
int k;
void Printarr(){
int i;
for(i=0; i<k; i++){
cout << heap[i] << " ";
}
cout << endl;
}
void deal(int x){
if(index < k){
heap[index++] = x;
if(index == k){
//堆化
MaxHeap(heap,k);
Printarr();
}
}else{
//x和堆顶进行比较,如果x大于堆顶,x将堆顶挤掉
if(x < heap[0]){
heap[0] = x;
MaxHeapFixDown(heap, 0, k);
Printarr();
}
}
}
int main() {
int x;
cin >> k;
cin >> x;
while(x!=-1){
deal(x);//处理x
cin >> x;
}
Printarr();
}
【4】串B是否包含串A的全部字符
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define MAX 10000
/**
* Case02串B是否包含串A的全部字符:
* 判断字符串A中的字符是否全部出现在字符串B中(大众点评笔试题)
* */
bool ContainsAll(string s1, string s2){
// const char *s2_arr = s2.data();
sort(s2.begin(), s2.end());
int i;
for(i=0; i<s1.length(); i++){
char a = s1.at(i);
int index = s2.find(a);
if(index < 0)
return false;
}
return true;
}
int main() {
string s1,s2;
cin >> s1 >> s2;
cout << ContainsAll(s1, s2);
}