算法设计与分析学习笔记04 | 8月更文挑战

202 阅读1分钟

这是我参与8月更文挑战的第4天,活动详情查看: 8月更文挑战

算法设计与分析题目1: 带权无向图G=(V, E)

每个顶点v∈G都有权值w(v)

设U是V的子集

U为图G的顶点覆盖:对任意边(u, v)∈E,有u∈U or v∈U

最小权顶点覆盖:顶点权之和最小

 

算法:

对于给定带权无向图G,用优先队列式分支界限法,计算最小权顶点覆盖

 

输入:

第1行:n个顶点(编号从1...n),m条边

第2行:n个顶点的权重

下面m行:表示边

 

输出:

第1行:最小权顶点的权重之和

第2行:对应的顶点

核心代码及注释:

/* 淘汰掉i的相邻点权重之和<i本身权重的点 */

for (int i = 0; i < n; ++i) {

int sum = -w[i];

int num = 0;

for (int j = 0; j < n; ++j) {

if (G[i][j]) {

sum += w[j];//保存i的相邻点的权重和

store[i][num++] = j;//存i的相邻点

}

}

//如果i的相邻点权重和<i的权重,淘汰,此时还没将flag[4]淘汰

if (sum <= w[i])

flag[i] = 0;

}

 

for (int i = 0; i < n; ++i) {
if (!flag[i]) continue;//被淘汰的点跳过

 

//只有权值大的可能被淘汰

for (int j = i + 1; j < n; ++j) {

if (w[i] > w[j]) {

//若i给j全覆盖,i被淘汰

if (TF(j, i))

flag[i] = 0;

}

else {

//若j给i全覆盖,j被淘汰

if (TF(i, j))

flag[j] = 0;

}

}

}

 

for (int i = 0; i < n; ++i) {

if (!flag[i]) continue;//被淘汰的点跳过

 

int num = 0;

for (int j = 0; j < n; ++j)

if (flag[j] && G[i][j])

++num;

//必选

if (num == 1)

flag[i] = 2;

}

测试结果: 输入:

7 7

1 100 1 1 1 100 10

1 6

2 4

2 5

3 6

4 5

4 6

6 7

输出:

图片1.png

算法设计与分析题目2

设计一个算法,求出无序整数数组中满足条件的最大乘积,给定一个无序数组,包含正数、负数和0,要求从中找出3个数的乘积,使得乘积最大,并且时间复杂度为O(n)、空间复杂度为O(1)。

核心代码及注释:

for(int i = 0; i < n; i++)

    {

        if(a[i] > max_1)

        {

            max_3 = max_2;

            max_2 = max_1;

            max_1 = a[i];

        }

        else if(a[i] > max_2)

        {

            max_3 = max_2;

            max_2 = a[i];

        }

        else if(a[i] > max_3)

            max_3 = a[i];

 

        if(a[i] < min_1)

        {

            min_2 = min_1;

            min_1 = a[i];

        }

        else if(a[i] < min_2)

            min_2 = a[i];

    }

 

    mul_max1 = max_1 * max_2 * max_3;

    mul_max2 = min_1 * min_2 * max_1;

    res_max = mul_max1 > mul_max2?mul_max1:mul_max2;

测试结果:

输入:

图片2.png

输出:

图片3.png

算法思想:因为存在正数和负数的原因,要找出三个数的乘积最大者,可能的情况为三个最大正数的乘积,和两个最小的负数与一个最大的正数的乘积,故核心思想在于找出最大的三个数和最小的两个数。