python升序数判断_【算法10】在升序数组中查找和等于给定值的两个数

【题  目】输入一个已经按升序排列的数组,一个给定的数字,在数组中查找两个数,使得它们的和等于给定的数字。要求时间复杂度为O(n),如果存在多对满足条件的数字对,只给出一对即可。例如:输入数组『1,2,4,7,11,15』,给定一个数字15,那么输出应该为『4,11』.

【思路1】我们先不考虑时间复杂度为O(n),按照最直观的思路来考虑,容易想到,我们一次固定数组中的一个数字,然后遍历这个数字之后的各个数字,判断和是否为给定的和,这样的时间复杂度为O(n2)。容易写出如下的代码:

1 #include

2 #include

3 using namespace std;

4

5 bool FindTwoNumbers(int array[],int length,int sum,int &num1,int &num2)

6 {

7 if(array == NULL || length < 2)

8 return false;

9

10 for(int i = 0;i < length - 1;++i)

11 {

12 for(int j = i + 1;j < length;++j)

13 {

14 if(array[i] + array[j] == sum)

15 {

16 num1 = array[i];

17 num2 = array[j];

18 return true;

19 }

20 }

21 }

22

23 return false;

24 }

25

26 int main()

27 {

28 cout<

29 int arraylength = 0;

30 cin>>arraylength;

31 int *p = new int[arraylength];

32

33 cout<

34 for(int i = 0;i < arraylength;++i)

35 {

36 cin>>p[i];

37 }

38

39 cout<

40 int result = 0;

41 cin>>result;

42

43 int a = 0;

44 int b = 0;

45 FindTwoNumbers(p,arraylength,result,a,b);

46

47 cout<

48 <

49

50 delete[] p;

51 return 0;

52 }

运行结果如下:

【思路2】上面的算法时间复杂度为O(n2),但是这个算法有一个好处就是,对于不排序的数组也是能够适用的,因为我们采用的方法是遍历,对于排序不排序,我们并不关心。这也从一个侧面说明了上面的算法时间复杂度较高的原因是:我们并没有充分利用数组是按升序排列的这个条件。如果考虑这个条件,我们会怎么做?

我们考虑一种特殊的情况,数组是严格的等差数列,那么给定一个和,如果能够找到一对整数满足题条件,那么根据等差数列的性质,较大的数想左移动一个数字,叫小的数向有移动一个数字,就又找到了另一对满足条件的数对。那么对于一般情况,我们能否这样考虑:首先判断第一个数字和最后一个数字的和,如果这个和大于给定的和,那么就让最后一个数字左移;反之,如果它们的和小于给定的和,就让第一个数字右移,这样是合乎逻辑的,然而这个算法容易使人产生一个疑问,会不会漏掉呢?这需要严格的数学证明,笔者暂时还不能给出证明,待日后补充,也希望数学很牛的同学不吝赐教。该思路代码如下:

1 #include

2 #include

3 using namespace std;

4 bool FindTwoNumbers(int array[],int length,int sum,int &num1,int &num2)

5 {

6 //无效输入,返回false7 if(array == NULL || length < 2)

8 return false;

9

10 int *start = &array[0];

11 int *end = &array[length -1];

12

13 while(start < end)

14 {

15 if((*start + *end) == sum)

16 {

17 num1 = *start;

18 num2 = *end;

19 return true;

20 }

21

22 //小于给定和,较小的数右移23 else if((*start + *end) < sum)

24 {

25 start++;

26 }

27

28 //大于给定和,较大的数左移29 else if((*start + *end) > sum)

30 {

31 end--;

32 }

33 }

34

35 return false;

36 }

37

38

39 int main()

40 {

41 cout<

42 int arraylength = 0;

43 cin>>arraylength;

44 int *p = new int[arraylength];

45

46 cout<

47 for(int i = 0;i < arraylength;++i)

48 {

49 cin>>p[i];

50 }

51

52 cout<

53 int result = 0;

54 cin>>result;

55

56 int a = 0;

57 int b = 0;

58 FindTwoNumbers(p,arraylength,result,a,b);

59

60 cout<

61 <

62

63 delete[] p;

64 return 0;

65 }

运行结果如下:

References:

注:

1)本博客所有的代码环境编译均为win7+VC6。所有代码均经过博主上机调试。

2)博主python27对本博客文章享有版权,网络转载请注明出处http://www.cnblogs.com/python27/。对解题思路有任何建议,欢迎在评论中告知。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值