不使用中间变量交换变量a、b的值的延伸

基础

为简单起见,用(x,y)表示变量a和b在某一时刻的一组值。

以交换a和b的值为例

(a,b)-->(a+b,b)-->(a+b,a)-->(b,a)

引申一

如果是改变三个变量的值呢?比如(a,b,c)-->(c,a,b)(向右循环移一位)

(a,b,c)-->(a+b,b,c)-->(a+b,b+c,c)-->(a+b,b+c,a+b+c)-->(c,b+c,a+b+c)-->(c,a,a+b+c)-->(c,a,b)

自然想到n,比如(a1,a2,...,an)-->(an,a1,a2,...,an-1)(不会输入下标……有谁知道怎么输入下标吗?)

(a1,a2,...,an)-->(a1+a2+...+an-1,a2,...,an-1,an)(第1个数等于前n-1个数之和)

-->(a1+a2+...+an-1, a2+...+an,...,an-1+an,an)(第2个到第n-1个数分别加上其后所有的数)

-->(a1+a2+...+an-1, a2+...+an,...,an-1+an, a1+a2+...+an)(最后一个数为所有数的和)

-->(an, a1, a1+a2, a1+a2+a3, ...,a1+a2+...+an-2, a1+a2+...+an)(最后一个数分别减去前面所有的数)

-->(an, a1, a2, a1+a2+a3, ...,a1+a2+...+an-2, a1+a2+...+an)(第三个数等于第三个数减去第二个数)

-->(an, a1, a2, a3, ...,an-2, an-1)(类似地,依次求得后面的数)

感觉好复杂!有没有简单的思路呢?

(a1,a2,...,an)-->(a1+a2+...+an,a2, a3, ...,an-1,an)(第一个数为所有数字之和)

-->(a1+a2+...+an,a1, a3, ...,an-1,an)(第二个数等于第一个数减去所有其他数字之和得到a1)

-->(a1+a2+...+an,a1, a2, ...,an-1,an)(第三个数等于第一个数减去所有其他数字之和得到a2)

同理可得所需结果。

分析:

给出的第二个算法简单明了,但每次都需要所有数字的参与。

对比两种算法,突然觉得,实际上可以构造出无数种计算的方法的,只要保证每次计算之后,n个数字所含的信息量不变,都是可以经过有限次运算恢复出所有数字的。

引申二

如果是无序地变换呢?(a1,a2,...,an)-->(b1,b2,...,bn),(b1,b2,...,bn)是(a1,a2,...,an)的一个排列

实际上,(a1,a2,...,an)和(b1,b2,...,bn)构成了(a1,a2,...,an)的一个置换。(离散数学、近世代数)

以下分析基于引申一中的第二个算法,目的是为了减少总的运算次数(加减法),使用了置换群中的相关知识。

一个定理:一个置换可分解为不相交的轮换之积。(应用近世代数第二版P63)

可以按照算法二依次处理每个轮换。

当然了,这样会增加总的赋值次数。效率是否有提升有待验证,毕竟增加了置换分解的操作。

引申三

在笔试、面试题中,一般还需要考虑a+b的溢出情况,由此而得到的解决方案是

(a,b)-->(a^b,b)-->(a^b,a)-->(b,a)

通过观察可以发现,只需把+、- 替换为^即可。

更多思考

如何优化算法?围绕赋值次数,总的运算次数(加减等操作)等。

1、引申一中给出的第二个算法的总的赋值次数为n+1,这个是最小的赋值次数了。但如何证明?

2、同时,这个算法每次都需要所有数字的参与,肯定可以通过增加赋值次数来减小总的运算次数,何时算法运行效率最佳?

3、更进一步,如何根据赋值次数为k的算法,构造出赋值次数为k+1的算法?是否可行?

反过来,如何根据赋值次数为k+1的算法,构造出赋值次数为k的算法?

4、给定k(k大于等于n+1),构造赋值次数为k的算法。是否任意的k都有一个算法呢?

给定k,构造赋值次数为k的,总的运算次数最少的算法。

5、编程实现。

后记

在看《计算机程序设计艺术》时,1.1算法的习题部分的第一个习题提到用最少的替代次数实现(a,b,c,d)-->(b,c,d,a),就想到了不使用中间变量的(a,b)-->(b,a),好奇地看了下答案,答案引入一个中间变量……也是五次替代。然后就思维发散了一下。

“更多思考”部分貌似是一大坑啊。

不知网上是否已经有过相关的分析,简单搜了下,暂时没有发现。

不使用中间变量交换变量a、b的值的延伸,码迷,mamicode.com

时间: 2024-10-25 11:30:10

不使用中间变量交换变量a、b的值的延伸的相关文章

通过位异或来交换a,b的值和通过中间变量交换a,b的值

//通过位异或来交换a,b的值 #include <stdio.h> int main(int argc, const char * argv[]) {    int a=20,b=10;    a=a^b;    b=b^a;    a=a^b;        printf("%d",a);    printf("%d\n",b); return 0;} //通过c来交换 #include <stdio.h> int main(int ar

不用中间变量交换A和B的值

public class SwapAB { public static void main(String[] args) { // 两种值交换的方式,用中间变量空间复杂度高于不用中间变量,但时间复杂度要低于不用中间变量. // 常规写两个值的交换 int a = 100; int b = 200; System.out.println("初始值 a=100 b=200"); // 中间变量 int c; // 复制给中间变量,临时存 c = a; // 把b的值赋给a. a = b;

不用中间变量交换a 和b的值

// 不用中间变量的写法 ,假如 a=13, b=8; a=a+b =21; //此时 a=21; b=8; b=a-b=13; //此时a=21; b=13; a=a-b=8; //相当于 a=21-13=8; // 第二种不用中间变量,换运算,效率比加法高点 a = a ^ b; b = a ^ b; a = a ^ b;

不用中间变量交换a和b的值?

a = 5 b = 6 a = a+b b = a-b a = a-b print(a,b) a = 5 b = 6 a = a^b b = b^a a = a^b print(a,b) a = 5 b = 6 a,b = b,a print(a,b) 输出 (6, 5) (6, 5) (6, 5) 原文地址:https://www.cnblogs.com/sea-stream/p/11192483.html

网络误区:不用中间变量交换2个变量的value,最高效的是异或运算.

本文记录了不使用中间变量交换2个变量的value,很多的网络留言说是直接异或运算就可以了,而且效率很高,是真的吗? 关于这个问题,网络上面有很多的解释,3种方法,我这里给比较一下各自的优缺点,然后简单分析一下汇编代码,分析代码如下: #include <stdio.h> void swap1(int &a,int &b) { int temp = a; a = b; b = temp; } void swap2(int &a,int &b) { a += b;

1108: 零起点学算法15——交换变量

1108: 零起点学算法15--交换变量 Time Limit: 1 Sec  Memory Limit: 64 MB   64bit IO Format: %lldSubmitted: 3266  Accepted: 1706[Submit][Status][Web Board] Description 水题 Input 输入2个整数(题目包含多组测试数据) Output 输出交换后的2个整数(每组测试数据一行,中间用空格隔开) Sample Input 825 23 Sample Outpu

不使用中间变量交换两个数. 求平均数考虑溢出

#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> //不使用中间变量交换两个数的值 void exchange_num(int *a, int *b) { ①* a =*a + *b;    //适用范围广 * b = *a -* b; * a =* a - *b; ②* a = (*a )*(*b); * b = (*a )/(*b); * a = (*a ) / (*b);//当两个数有

c#交换变量的几种方法(笔试之一)

大家很熟悉知道,交换变量经常的使用的一种方法是使用第三个变量,也符合正常人的思维逻辑,但是还有其他的一些方法来实现,但是有点“偏门”,记住就好了.下面就列举这几种方法. 第一种方法,会用到参数的方法再来修稿. 1 using System; 2 namespace Exercise 3 { 4 class Program 5 { 6 private static void Main(string[] args) 7 { 8 int num1 = 10; 9 int num2 = 5; 10 in

一种节省空间的交换变量的基本算法

一种节省空间的交换变量的基本算法,一个很简单的算法 因为其中没有引入temp变量,所以可以节省空间 代码如下: 一种节省空间的交换变量的基本算法