左神算法笔记(异或)+C语言实现

简介: 异或性质运算性质应用举例1、不用额外变量,交换两个数的值原理代码2、找到数组中唯一一个出现奇数次的数字3、提取最右侧的1(常用)应用1:找到数组中唯二出现的两个出现奇数次的数字代码应用2:找到二进制有多少1代码

性质


1、相同为0,不同为1

记为不进位相加


运算性质


2、异或运算的性质:A^0=A A^A=0

满足交换律、结合律(多个^顺序不影响答案)


应用举例


1、不用额外变量,交换两个数的值


a=a^b
b=a^b
a=a^b


原理


  int a=甲,int b=乙
    a = 甲^乙
    b = 甲^乙^乙
    a = 甲^乙^乙^甲^乙
  (前提:a,b地址不同)


代码


#include <stdio.h>
int change(int a,int b) {
  a = a ^ b;
  b = a ^ b;
  a = a ^ b;
  printf("a=%d\nb=%d",a,b);
  return 0;
}


2、找到数组中唯一一个出现奇数次的数字


全部异或起来即可


3、提取最右侧的1(常用)


A&(~A)+1


应用1:找到数组中唯二出现的两个出现奇数次的数字


先找到数组全部异或起来以后结果最右侧的1出现在哪一位x


根据第x位是1或0将数组分成两组,分别全部异或,即得结果。


代码


#include <stdio.h>
#include <stdlib.h>
int two_oddTimes_numb(int list[], int size) {
  int i, j ,rightone;
  int eor = 0;
  for (i = 0; i < size; i++) {
    eor ^= list[i];
  }
  rightone = eor & (~eor) + 1;
  //用&实现分组^
  int ans = 0;
  for (j = 0; j < size;j++) {
    if ((list[j] & rightone) != 0) {
      ans ^= list[j];
      printf("%d\n",list[j]);
    }
  }
  char string1[33],string2[33],string3[33];
  _itoa_s(eor, string1, 33, 2);
  _itoa_s(ans, string2, 33, 2);
  _itoa_s(ans^eor, string3, 33, 2);
  printf("库函数得到的二进制为:%s\r\n", string1);
  printf("库函数得到的二进制为:%s\r\n", string2);
  printf("库函数得到的二进制为:%s\r\n", string3);
  printf("两个出现奇数次的数为:%d和%d\n",ans,ans^eor);
  return 0;
}


刚学C,一开始没有初始化eor,以为是默认的0,结果编译可以通过,编译器也没给我提示必须必须初始化。就是结果不对,懵了很久。

结果原因就是C没有默认是0的说法,只声明一个变量只会给他一块地址,里面还有之前系统放的垃圾数据(操作系统回收内存空间时,并不清空该内存空间中遗留下来的数据)

编译器如果发现一个变量里面存放的是一个垃圾值,就认为没有给它赋初值,那么系统就会自动将一个很小的,如 –858993460 这个填充数字给放进去。所以我们看到的结果都是一个不变的值。

还有就是直接printf未初始化的数据会报错,使用这个未初始化的数进行一番操作以后再printf又不会报错了。

我用的visual studio 2022版的,转二进制的时候报itoa()不能用了,要用_itoa_s(int 要转换的数字,char 存放转换结果的字符串,size_t 存放结果的字符数组长度,int 转化的进制数,2表示2进制,10表示10进制),比原来多了一个字段,size_t 类型表示C中任何对象所能达到的最大长度,它是无符号整数。


应用2:找到二进制有多少1


只要还不是1,就一直和自己提取的右边第一个1^,同时计数。


代码


#include <stdio.h>
#include <stdlib.h>
int find_1Times(int a) {
  char str[33];
  _itoa_s(a, str, 33, 2);
  printf("二进制为:%s\n", str);
  int times = 0,tmp =0;
  while (a != 0) {
    //去掉最后一个1
    tmp = a & ((~a) + 1);
    times++;
    a ^= tmp;
  }
  printf("有%d个1\n", times);
}


相关文章
|
2月前
|
自然语言处理 算法 搜索推荐
C语言中谈论算法
C语言中谈论算法
11 0
C语言中谈论算法
|
4天前
|
存储 缓存 算法
【C 言专栏】C 语言实现算法的高效性
【5月更文挑战第6天】本文探讨了C语言在实现高效算法上的优势,包括其高效性、灵活性、可移植性和底层访问能力。关键点包括选择合适的数据结构(如数组、链表、树和图)、应用优化策略(如减少计算、空间换时间、分治和动态规划),以及内存管理和代码优化技巧。通过实际案例(如排序和图遍历算法),阐述了如何利用C语言实现算法高效性,并强调在实践中不断探索和优化以提升算法效率。C语言在计算机科学中的重要地位使其成为实现高效算法的首选工具。
【C 言专栏】C 语言实现算法的高效性
|
4天前
|
搜索推荐 C语言
【C语言/数据结构】排序(归并排序|计数排序|排序算法复杂度)
【C语言/数据结构】排序(归并排序|计数排序|排序算法复杂度)
8 0
|
9天前
|
机器学习/深度学习 算法 C语言
【C言专栏】递归算法在 C 语言中的应用
【4月更文挑战第30天】本文介绍了递归算法在C语言中的应用,包括基本概念(通过调用自身解决子问题)、特点(调用自身、终止条件、栈空间)和实现步骤(定义递归函数、分解问题、设置终止条件、组合解)。文中通过阶乘计算和斐波那契数列两个案例展示了递归的使用,强调了递归可能导致的栈溢出问题及优化需求。学习递归有助于理解和应用“分而治之”策略。
|
17天前
|
算法 搜索推荐 C语言
C语言用流程图表示算法
C语言用流程图表示算法
19 0
|
29天前
|
搜索推荐 算法 C语言
【排序算法】C语言实现随机快排,巨详细讲解
【排序算法】C语言实现随机快排,巨详细讲解
|
29天前
|
搜索推荐 C语言 C++
【排序算法】C语言实现归并排序,包括递归和迭代两个版本
【排序算法】C语言实现归并排序,包括递归和迭代两个版本
|
29天前
|
搜索推荐 算法 C语言
【排序算法】C语言实现选择排序与冒泡排序
【排序算法】C语言实现选择排序与冒泡排序
|
1月前
|
机器学习/深度学习 存储 算法
初阶数据结构之---导论,算法时间复杂度和空间复杂度(C语言)
初阶数据结构之---导论,算法时间复杂度和空间复杂度(C语言)
|
1月前
|
算法 C语言
【算法与数据结构】 C语言实现单链表队列详解2
【算法与数据结构】 C语言实现单链表队列详解