IT公司100题-32-求数组的最大子序列的和

问题描述:

有两个整数序列a, b,大小都为n, 序列元素的值任意整数,无序。

要求:通过交换a, b 中的元素,使得sum(a)-sum(b),差最小。

例如:

var a=[80, 40, 60, 10, 20, 30];

var b=[10, 20, 50, 40, 30, 20];

分析:

近似最优算法:
当前数组a和数组b的和之差为:A = sum(a) – sum(b),a的第i个元素和b的第j个元素交换后,a和b的和之差为:
A’ = (sum(a) – a[i] + b[j]) – (sum(b) – b[j] + a[i])
= sum(a) – sum(b) – 2 (a[i] – b[j])
= A – 2 (a[i] – b[j])
设x= a[i] – b[j],A’ = A-2x,只要 0 < x <= A/2,则A’ < A。
所以,目标就是寻找i和j,使得x在0和A/2之间,并且越接近A/2越好。直到找不到这样的x为止。

代码实现:

 1 // 32.cc
 2 #include <iostream>
 3 using namespace std;
 4
 5 // 计算数组的和
 6 int sum(const int* a, int n) {
 7     int count = 0;
 8     for (int i = 0; i < n; i++)
 9         count += a[i];
10     return count;
11 }
12
13 // 交换数组元素得到平衡集
14 void balance_swap(int* a, int* b, int n) {
15     // a指向和比较大的集合
16     if (sum(a, n) < sum(b, n)) {
17         int* t = a;
18         a = b;
19         b = t;
20     }
21
22     bool loop = true;
23     while (loop) {
24         loop = false;
25         for (int i = 0; i < n; i++) {
26             for (int j = 0; j < n; j++) {
27                 int diff = a[i] - b[j];
28                 int A = sum(a, n) - sum(b, n);
29                 if (diff > 0 && diff < A / 2) {
30                     loop = true;
31                     int tmp = a[i];
32                     a[i] = b[j];
33                     b[j] = tmp;
34                 }
35             }
36         }
37     }
38 }
39
40 // 打印数组元素
41 void print(const int* a, int n) {
42     for (int i = 0; i < n; i++)
43         cout << a[i] << " ";
44     cout << endl;
45 }
46
47 int main() {
48     int a[] = {80, 40, 60, 10, 20, 30};
49     int b[] = {10, 20, 50, 40, 30, 20};
50     int n = sizeof(a) / sizeof(int);
51
52     balance_swap(a, b, n);
53
54     print(a, n);
55     print(b, n);
56
57     return 0;
58 }

输出:

$ ./a.exe
50 40 60 10 20 30
10 20 80 40 30 20
时间: 2024-11-08 21:35:35

IT公司100题-32-求数组的最大子序列的和的相关文章

IT公司100题-14-排序数组中和为给定值的两个数字

问题描述: 输入一个升序排序的数组,给定一个目标值target,求数组的两个数a和b,a+b=target.如果有多个组合满足这个条件,输出任意一对即可. 例如,输入升序数组[1, 3, 4, 5, 13, 17]和目标值20.输出3和17. 分析: 最简单的办法,直接遍历,时间复杂度为O(n^2). 双下标法:low和high a[low]+a[high] < target, low++; a[low]+a[high] > target, high–; a[low]+a[high] == t

IT公司100题-12-求1+2+…+n

问题描述: 求1+2+…+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字以及条件判断语句(A?B:C). 分析: 利用类的静态变量实现: new一含有n个这种类的数组,那么该类的构造函数将会被调用n次. 代码实现: 1 // 12.cc 2 #include <iostream> 3 using namespace std; 4 5 class Object { 6 public: 7 Object() { 8 ++N; 9 Sum += N; 10

IT公司100题-11-求二叉树中节点的最大距离

问题描述: 写程序,求一棵二叉树中相距最远的两个节点之间的距离. 10/     \6      14/   \   /   \4    8 12    16 分析: 二叉树中最远的两个节点,要么是根和一个叶子节点,要么是两个叶子节点. 代码实现: 1 // 11.cc 2 #include <iostream> 3 using namespace std; 4 5 typedef struct BSTreeNode { 6 int data; 7 BSTreeNode *left; 8 BS

IT公司100题-3

题目:输入一个整形数组,数组里有正数也有负数.数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值.要求时间复杂度为O(n). 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18. 分析:本题最初为2005年浙江大学计算机系的考研题的最后一道程序设计题,在2006年里包括google在内的很多知名公司都把本题当作面试题.由于本题在网络中广为流传,本题也顺利成为2006

IT公司100题-9-判断整数序列是不是二元查找树的后序遍历结果

问题描述: 输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果. 如果是返回true,否则返回false. 例如输入4, 8, 6, 12, 16, 14, 10,由于这一整数序列是如下树的后序遍历结果: 10/     \6      14/  \    /   \4   8 12    16 因此返回true. 如果输入6, 5, 8, 5, 7 ,则返回false. 分析: 在后续遍历得到的序列中,最后一个元素为树的根结点.根节点元素将数组分为两部分,左边都小于根节点,右边都大

IT公司100题-25-求字符串中的最长数字串

问题描述: 实现一个函数,求出字符串中的连续最长数字串.例如输入”12345cbf3456″,输出”12345″. 函数原型为: void conti_num_max( const char * src, char * dest); dest保存最长数字串,返回void. 分析: 遍历一遍字符串,记录起始位置和长度即可. 代码实现: 1 // 25.cc 2 #include <iostream> 3 #include <cstring> 4 using namespace std

IT公司100题-18-圆圈中最后剩下的数字

问题描述: n个数字(下标为0, 1, …, n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字(当前数字从1开始计数).当一个数字被删除后,从被删除数字的下一个数字开始计数,继续删除第m个数字.求这个圆圈中剩下的最后一个数字. 分析: 这是有名的约瑟夫环问题. 最直接的方法: 使用链表来模拟整个删除过程.因为需要n个链表节点,所以空间复杂度为O(n).每删除一个节点,都需要m次运算,所以时间复杂度为O(mn). 实现代码如下所示: 1 // 18_1.cc 2 #include

IT公司100题-13-求链表中倒数第k个结点

问题描述: 输入一个单向链表,输出该链表中倒数第k个结点.链表倒数第0个节点为NULL. struct list_node { int data; list_node* next; }; 分析: 方法1: 首先计算出链表中节点的个数n,然后倒数第k个节点,为正数n-k+1个节点. 需要遍历链表2次. 方法1代码实现: 1 // 13_1.cc 2 #include <iostream> 3 using namespace std; 4 5 struct list_node { 6 int da

IT公司100题-2

1 // 定义栈的数据结构,要求添加一个min 函数,能够得到栈的最小元素. 2 // 要求函数min.push 以及pop 的时间复杂度都是O(1). 3 #include <iostream> 4 #include "../data/own/c2_list.h" 5 using namespace std; 6 7 template <typename object> 8 class miniStack{ 9 public: 10 bool isEmpty(

IT公司100题-26-左旋转字符串

问题描述: 给定字符串和左旋的字符数,写程序实现字符串的左旋操作.例如对于字符串”12345678″, 左旋转4个字符后,变成”56781234″.要求时间复杂度为O(n),空间复杂度O(1). 分析: 假设字符串表示为XY,X表示需要左旋的部分,左旋后字符串表示为YX. 根据公式: 代码实现: 1 // 26.cc 2 #include <iostream> 3 #include <string> 4 #include <cstring> 5 using namesp