几个简单的字符串和数组计算方法

本文介绍了四种数组操作技巧:寻找两个数的和等于给定值、找出连续正数序列之和等于目标值、找到数组中绝对值最小的数以及计算逆序对总数。通过具体的算法实现,帮助读者理解和掌握这些实用的编程技巧。

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~67~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-12, 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值