不用比较和判断得到两个数中的最大值
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <stdbool.h>
#define u unsigned
#define ll long long
#define sc scanf
#define pr printf
#define fr(i, j, n) for (int i = j; i < n; i++)
#define N 1001
int max(int a, int b);//返回两个数中的最大值
int sign(int n);//返回n的符号位并翻转,也就是代表负数返回0,非负数返回1
int flip(int n);//使n的最低位翻转
int main(int argc, char* argv[])
{
pr("%d", max(3, 3));
return 0;
}
int max(int a, int b)
{
int c = a - b;//计算a和b的差值
int sa = sign(a);//得到a的符号,如果a是负数返回0,不是返回1
int sb = sign(b);//得到b的符号,如果b是负数返回0,不是返回1
int sc = sign(c);//得到c的符号,如果c是负数返回0,不是返回1
int diff = sa ^ sb;//a和b的符号相同是1,不同为0
int same = flip(diff);//两种状态互斥,所以直接翻转就行了。
int returnA = same * sc + diff * sa;//如果a和b符号相同并且c是个非负数代表a是最大的,或者a和b符号不相同并且a是个非负数,那么返回a
//因为diff和same互斥,所以只会中一边相当于if,这里还是很妙的
int returnB = flip(returnA);
//只可能返回一个数所以returnA和returnB也互斥,直接翻转就可以了。
return returnA * a + returnB * b;//returnA是1代表返回a,returnA是0代表返回b,returnA和returnB互斥,所以只会有一个是0,另一个是1
}
int sign(int n)
{
return flip((n >> 31) & 1);//负数返回0,非负数返回1
}
int flip(int n)//n只能使0或者1
{
return n ^ 1;
}
一个数组中有两个数出现了奇数次,其他数出现了偶数次,求出这出现奇数次的两个数
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* singleNumber(int* nums, int numsSize, int* returnSize) {
int ans = 0;//把所有数异或起来,最后ans的值是两个奇数的异或的结果
for (int i = 0; i < numsSize; i++) {
ans ^= nums[i];
}
//防止溢出,因为INT_MIN无法的到它的绝对值
int r = ans == INT_MIN? ans: ans & (1 * -ans);//取出ans的最右边的1
int res = 0;//去异或在二进制中有ans最右边的1的数,最后res一定是两个数中的一个
for (int i = 0; i < numsSize; i++) {
if (nums[i] & r) {
res ^= nums[i];
}
}
int* p = (int*)malloc(sizeof(int) * 2);
*returnSize = 2;
p[0] = ans ^ res;//根据异或的性质来求出另一个数
p[1] = p[0] ^ ans;//根据异或的性质来求出另一个数
return p;
}
异或运算符是满足结合律和交换律的,然后相同的数异或的结果是0,一个数和零异或还是它本身。
标签:返回,returnA,运算,int,负数,异或,ans,操作 From: https://www.cnblogs.com/lwj1239/p/17917536.html