1. 给定一个递增数组和一个数字S,在数组中找到两个数使得它们之和正好是S。
思路:设定该数组的首尾的下标begin和end,当begin<end时,计算arr[end]和sum-arr[begin]的大小关系,适当的情况下使end—或 begin++;
#include <iostream>
using namespace std;
int arr[100];
int main()
{
int n =0,i;
cin>>n;
int begin = 0;
int end = n-1;
for(i=0;i<n;i++)
{
cin>>arr[i];
} //输入有序递增的数组
int sum;
bool flag = false;
cin >> sum; //输入待求得数字
if(sum<=arr[0])
cout<<"sum is smaller than the smallest num in arr.";
else
{
while(begin <end)
{
int temp = sum - arr[begin];
while(arr[end] > temp&&begin<end)
end --;
if(arr[end]== temp &&begin<end)
{
printf("arr[%d] = %d; arr[%d] = %d\n",
begin,arr[begin],end,arr[end]);
begin++;
flag = true;
}
else
begin++;
}
}
if(!flag)
cout<<”no right results!”;
return 0;}
2. 输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。如输入15,结果打印为1~5、 4~6和7~8.
思路:可以预设两个整数num1 = 1;num2 =2; 则sum = num1 + num2; 如果sum小于输入的数x,就使num2++; sum += num2;继续比较sum和x;如果x<sum,那么使num1++; sum -= num1;如果x == sum,打印num1~num2的序列;继续循环使num1++;直到num1 < (x+1)/2。
#include <iostream>
using namespace std;
int main()
{
int x;
cin>>x;//输入待求数字
if(x<3)
cout<<"输入参数错误!"<<endl;
int num1 = 1, num2 = 2;
int sum = num1 + num2;
while(num1 < (x+1)/2)
{
if(x>sum)
{
num2++;
sum += num2;
}
else if(x<sum)
{
sum -= num1;
num1 ++;
}
if(x == sum)
{
for(int i=num1; i<=num2;i++)
cout<<i<<" ";
cout<<endl;
sum -= num1;
num1++;
}
}
return 0;
}
3. 给出一个递增数组,有正数或负数,找到其中绝对值最小的数。数组{-8,-5,-1,2, 4},绝对值最小的数是-1。
思路:利用二分查找方法,则数组中绝对值最小的数必定在既有正数又有负数的子数组内。在做二分查找前要处理全为负数的数组和全为正数的数组。
#include <iostream>
using namespace std;
int myabs(int num)
{
if(num <0)
num = -num;
return num;
}
void binary_search(int arr[], int low, int high) //二分查找
{
if(low > high)
{
cout<<"input error!"<<endl;
return;
}
if(low == high)
{
printf("the min_abs_num is arr[%d] = %d\n",low,arr[low]);
return;
}
int middle = (low + high)/2;
if(myabs(arr[middle]) > myabs(arr[middle+1]))
binary_search(arr,middle+1,high);
else
binary_search(arr, low, middle);
}
void find_min_abs_in_arr(int *arr, int low, int high)
{
if(NULL == arr)
{
cout<<"input error!"<<endl;
return;
}
if(arr[high]<=0) //全是负数的情况
cout<<"the min abs_num is:"<<arr[high]<<endl;
else if(arr[low]>=0)//全是正数的情况
cout<<"the min abs_num is:"<<arr[low]<<endl;
else //既有正数又有负数的情况
binary_search(arr,low,high);
}
int main()
{
int arr[100];
int n;
cin>>n;
for(int i =0; i<n; i++)
cin>>arr[i];
find_min_abs_in_arr(arr,0,n-1);
return 0;
}
4. 在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。例如:在数组{6,3,7,2}中,一共存在4个逆序对,分别是(6,3)、(6,2)、(3,2)、(7,2)。
1).最容易想到的方法是暴力搜索法,但时间复杂度是O(n2)
2).下面介绍一个效率比较高方法。即利用分治的策略。分治的策略是将数组进行二分划分,比较常见的归并排序。对于本题目:如果只有两个数字的数组(如{6,4}),那么它的逆序对个数可以容易的求出;如果给这个数组添加一个数字放在数组头(如{5,6,4});那么该数组的逆序对就应该是数组{6,4}的逆序对加上5和6或4组成的逆序对。想一想在归并排序中的情况:由于两个子数组已经是拍好序的,因此拿出第一个数组的最大数字和第二个数组的最大数字进行比较,如果大于,则对应合并后的逆序对要多出第二个数组的长度,即second – middle;(如下面代码所示)具体算法如下:
#include <iostream>
#include <cassert>
using namespace std;
void merge_child_arr(int arr[], int low, int middle,int high, int *ptemp,int &ncount)
{
int first = middle, second = high;
//int *temp = ptemp;
int i = high;
while((first>=low)&&(second>=middle +1))
{
if(arr[first] > arr[second])
{
ncount += second - middle;//计算逆序对个数的核心;可以用实例分析下
ptemp[i--] = arr[first--];
}
else
{
ptemp[i--] = arr[second--];
}
}
while(first >= low)
ptemp[i--] = arr[first--];
while(second >= middle+1)
ptemp[i--] = arr[second--];
for (int i=low; i<=high; i++)
{
arr[i] = ptemp[i];
}
}
void divide_child_arr(int arr[], int low, int high, int *ptemp, int &ncount)
{
assert(arr!=NULL && low>=0 &&high>=0);
if(high>low)
{
int n_mid = (low + high)/2;
divide_child_arr(arr, low, n_mid, ptemp,ncount);
divide_child_arr(arr, n_mid+1, high, ptemp,ncount);
merge_child_arr(arr,low,n_mid,high,ptemp,ncount);
}
else
return;
}
int reverse_count(int arr[], int len)
{
if(arr == NULL || len<0)
return -1;
int ncount = 0;
int *ptemp = new int[len];
memset(ptemp,0,len*sizeof(int));
divide_child_arr(arr,0,len-1,ptemp,ncount);
cout<<"the sorted arr is :";
for(int i =0; i<len; i++)
cout<<ptemp[i]<<" ";
cout<<endl;
delete ptemp;
ptemp = NULL;
return ncount;
}
int main()
{
int arr1[] = {7,5,6,4,8};
cout<<"the num of reverse arr_pair is:"<<reverse_count(arr1,5)<<endl;
int arr2[] = {4,5,6,7,8};
cout<<"the num of reverse arr_pair is:"<<reverse_count(arr2,5)<<endl;
return 0;
}
本文介绍了四种数组操作技巧:寻找两个数的和等于给定值、找出连续正数序列之和等于目标值、找到数组中绝对值最小的数以及计算逆序对总数。通过具体的算法实现,帮助读者理解和掌握这些实用的编程技巧。
4

被折叠的 条评论
为什么被折叠?



