算法:数组 C++

题目来自于

http://zhedahht.blog.163.com/blog/#m=0&t=1&c=fks_081075092084086069082074084070080087080066083082

非常感谢何海涛 July大神和众网友。


本博文初衷是为了方便自己准备面试,有一篇文章可以看所有的东西,省的翻来翻去。

代码是手打的Qt C++,解法中不考虑实现最简单的毫无难度的暴力解法了。

因为很短,不区分*.cc和*.hh文件了,都写在一起; 注释初衷也是为了自己理解。

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

1.1程序员面试题精选100题(10)-排序数组中和为给定值的两个数字[算法] 

题目描述:

输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。

例如输入数组12471115和数字15。由于4+11=15,因此输出411


分析与C++代码:

// 程序员面试题精选100题(10)-排序数组中和为给定值的两个数字[算法]

// 题目: 输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,
// 使得它们的和正好是输入的那个数字。要求时间复杂度是O(n)。
// 如果有多对数字的和等于输入的数字,输出任意一对即可。
// 例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。
#include<iostream>
using namespace std;
bool findTwoNumbers(const int* arr, size_t arrLength, int target, int& index1, int& index2);
int main()
{
    int test[] = {1, 2, 4, 11, 15};
    size_t testLength = sizeof(test)/sizeof(test[0]);
    int target = 15;
    int index1 = 0, index2 = 0;
    if (findTwoNumbers(test, testLength, target, index1, index2))
    {
        cout << test[index1] << " + " << test[index2] << " = " << target << endl;
    }else
    {
        cout << "failed to find out such two numbers!" << endl;
    }
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 推荐解法: 两边逼近
// 如果我们不考虑时间复杂度,最简单想法的莫过去先在数组中固定一个数字,
// 再依次判断数组中剩下的n-1个数字与它的和是不是等于输入的数字。可惜这种思路需要的时间复杂度是O(n2)。
// 我们假设现在随便在数组中找到两个数。如果它们的和等于输入的数字,那太好了,
// 我们找到了要找的两个数字;如果小于输入的数字呢?我们希望两个数字的和再大一点。
// 由于数组已经排好序了,我们是不是可以把较小的数字的往后面移动一个数字?
// 因为排在后面的数字要大一些,那么两个数字的和也要大一些,就有可能等于输入的数字了;
// 同样,当两个数字的和大于输入的数字的时候,我们把较大的数字往前移动,因为排在数组前面的数字要小一些,
// 它们的和就有可能等于输入的数字了。
// 我们把前面的思路整理一下:最初我们找到数组的第一个数字和最后一个数字。
// 当两个数字的和大于输入的数字时,把较大的数字往前移动;当两个数字的和小于数字时,把较小的数字往后移动;
// 当相等时,打完收工。这样扫描的顺序是从数组的两端向数组的中间扫描。
//
// 如果数组未排序,先排序O(nlogn),如果是三个数的和,先固定数组里的一个数arr[0],在用
// 上面的方法找两个数=target-arr[0] for all arr[ii] O(n^2) in total
bool findTwoNumbers(const int* arr,  size_t arrLength, int target, int& index1, int& index2)
{
    if (arr == NULL || arrLength <= 0)
    {
        return false;
    }
    index1 = 0;
    index2 = arrLength - 1;
    while(index1 < index2)
    {
        // 细节,两个整数相加可能会溢出
        long long curSum = arr[index1] + arr[index2];
        if (curSum < target)
        {
            index1++;
        }else if(curSum == target)
        {
            return true;
        }else
        {
            index2--;
        }
    }
    return false;
}

1.2 调整数组顺序使奇数位于偶数前面[算法] 

题目描述:

输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。要求时间复杂度为O(n)

分析与C++代码:

// 程序员面试题精选100题(29)-调整数组顺序使奇数位于偶数前面[算法]

// 题目: 输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,
// 所有偶数位于数组的后半部分。要求时间复杂度为O(n)。
#include<iostream>
#include<string>
using namespace std;
void myPrint(int arr[], size_t arrLength, string header)
{
    cout << header << ": ";
    for(size_t ii = 0; ii < arrLength; ++ii)
    {
        cout << arr[ii] << " ";
    }
    cout << endl;
}
bool oddEvenSort(int arr[], size_t arrLength);
int main()
{
    int test[] = {2,4,6,8, 1, 3, 5, 7};
    size_t testLength = sizeof(test)/sizeof(test[0]);
    myPrint(test, testLength, "before");
    if(oddEvenSort(test, testLength))
    {
        myPrint(test, testLength, "after");
    }else
    {
        cout << "error!" << endl;
    }
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// 推荐解法: 前后交换
// 要求的是把奇数放在数组的前半部分,偶数放在数组的后半部分,因此所有的奇数应该位于偶数的前面。
// 也就是说我们在扫描这个数组的时候,如果发现有偶数出现在奇数的前面,我们可以交换他们的顺序,交换之后就符合要求了。
// 因此我们可以维护两个指针,第一个指针初始化为数组的第一个数字,它只向后移动;
// 第二个指针初始化为数组的最后一个数字,它只向前移动。在两个指针相遇之前,第一个指针总是位于第二个指针的前面。
// 如果第一个指针指向的数字是偶数而第二个指针指向的数字是奇数,我们就交换这两个数字。
// 顺便复习下宏函数,就不写到文件顶部了
// 能加括号就加括号!!
// 注意不要加;写成语句e.g. {((x)%2)?(false):(true);}
// 要写成表达式
//#define isEven(x) (((x)%2)?false:true)
// 位运算比较快
#define isEven(x) (((x)&1) == 0?true:false)
// 不用中间变量交换两个数,并避免overflow问题
// 异或XOR
// http://blog.csdn.net/lpt19832003/article/details/5334688
#define mySwap(num1, num2) \
{ \
    (num1) = (num1) ^ (num2);\
    (num2) = (num2) ^ (num1);\
    (num1) = (num1) ^ (num2);\
}
// 将来还可扩展为函数指针,相应的把宏改写为inline 函数
// bool oddEvenSort(int arr[], size_t arrLength, bool (*func)(int))
bool oddEvenSort(int arr[], size_t arrLength)
{
    if (arr == NULL || arrLength <=0)
    {
        return false;
    }
    int index1 = 0;
    int index2 = arrLength - 1;
    while(index1 < index2)
    {
        // 如果index1现在指向奇数,不用交换
        if (!isEven(arr[index1]))
        {
            index1++;
            continue;
        }
        // 如果index2现在指向偶数,不用交换
        if (isEven(arr[index2]))
        {
            index2--;
            continue;
        }
        // 如果index1指向偶数 AND index2指向奇数 交换
        mySwap(arr[index1], arr[index2]);
    }
    return true;
}

1.3 数组中只出现一次的数字[算法]

题目描述:

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)

分析和C++代码:

1.3 数组中只出现一次的数字[算法]

题目描述:

分析和C++代码:

1.3 数组中只出现一次的数字[算法]

题目描述:

分析和C++代码:

1.3 数组中只出现一次的数字[算法]

题目描述:

分析和C++代码:

1.3 数组中只出现一次的数字[算法]

题目描述:

分析和C++代码:

1.3 数组中只出现一次的数字[算法]

题目描述:

分析和C++代码:

1.3 数组中只出现一次的数字[算法]

题目描述:

分析和C++代码:

1.3 数组中只出现一次的数字[算法]

题目描述:

分析和C++代码:




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值