位运算

基础知识

& 与
| 或
~ 非
^ 异或
>> 右移 :随笔记忆_#include
<< 左移 : 随笔记忆_汉明距离_02

随笔记忆_i++_03

常用操作

  1. x & 1 可以用来判断x的奇偶性,等于1就是奇数,等于0是偶数。
  2. x = x & (x -1) 可以清掉x最低位的1
  3. 求x的第k位数字:x >> k & 1
  4. 返回x的最后一位1: lowbit(x) = x&(~x+1) = x & -x
  5. 把x的第n位的值设置为1:x | (1 << n)
  6. 把x的第n位的值设置为0:x & (~(1 << n))

应用

  1. 给定一个整数判断他是不是2的幂次方数。(Leetcode231)
class Solution {
public:
    bool isPowerOfTwo(int n) {
        
        
    if (n == 0) return false;
    while (n % 2 == 0) n /= 2;
    return n == 1;
        
        
        
    }
};class Solution {
public:
    bool isPowerOfTwo(int n) {
        
        
        if(n == 0) return false;
        long long x = n;
        return (x & (-x)) == x; 
        
        
    }
};class Solution {
  public:
  bool isPowerOfTwo(int n) {
      
    if (n == 0) return false;
    long long x = n;
    return (x & (x - 1)) == 0;
   
  }
};
  1. 求该数二进制表示中位为1的个数。(leetcode 191)
public class Solution {
    public int hammingWeight(int n) {
        
        
        int count = 0;
        while (n != 0) {
            n = n &(n -1);
            count++;
        }
        return count;
        
        
    }
}#include<cstdio>
int main()
{
int n;
scanf("%d",&n);
while(n)
{
    printf("%d",n%2);
    n/=2;
}
return 0;
}
  1. 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
#include<cstdio>
int a[100];
int main()
{
    int n;
    scanf("%d",&n);
    int res = 0;
    for(int i = 1;i <=n; i++)
    {
        scanf("%d", &a[i]);
        res^=a[i];
    }
    printf("%d",res);

    return 0;
}
  1. 不使用第三个变量的情况下交换两个变量的值。
x = x ^ y   // (1)
y = x ^ y   // (2)
x = x ^ y   // (3)


  1. 汉明距离(练习)

题目461-两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目。给出两个整数 x 和 y,计算它们之间的汉明距离。注意:0 ≤ x, y < 2^31。 来源:力扣(LeetCode)链接:力扣

快速排序

基本思想:分治

步骤

  1. 确定分界点x
  2. 调整顺序,分割成独立的两部分,小于等于x的数在左半边,大于等于x的在右半边
  3. 递归处理左右两段
#include<iostream>
using namespace std;
const int N = 100005;
int a[N], n;
void quick_sort(int l, int r)
{
    if(l >= r) return;
    int i = l - 1, j = r + 1, x = a[l + r >> 1];
    while(i < j)
    {
        while(a[++i] < x);
        while(a[--j] > x);
        if(i < j) swap(a[i], a[j]);
    }
    quick_sort(l, j);
    quick_sort(j + 1, r);
}
int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)scanf("%d", &a[i]);
        
    quick_sort(1, n);
    
    for(int i = 1; i <= n; i++) printf("%d ", a[i]);
    return 0;
}

注意边界问题

quick_sort(l, i - 1);
quick_sort(i, r);

2

1 2

用 i 就不要去a[l]做边界,需要a[l + r + 1 >> 1] 或者 a[r]。

同理,上述代码j不能用r做边界,用a[l+r>>1] 或者 a[l]。

应用

第k个数

给定一个长度为n的整数数列,以及一个整数k,请用快速选择算法求出数列从小到大排序后的第k个数。

#include<iostream>
using namespace std;
const int N=100005;
int n,a[N];
int quick_sort(int l,int r,int k)
{
	if(l>=r) return a[l];
    int i= l - 1,j = r + 1,x = a[l+r>>1];
    while(i<j)
    {
        while(a[++i]<x);
        while(a[--j]>x);
        if(i<j) swap(a[i],a[j]);
    }
    
    if(j - l + 1 >= k)
        quick_sort(l,j,k);
    else
        quick_sort(j+1,r,k-(j-l+1));
    
}
int main()
{
    int k;
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    printf("%d",quick_sort(0,n-1,k));
 
    return 0;
}

选择排序

基本思想:

每趟排序在当前待排序序列中选出关键码最小的记录,添加新的最左边。

简单选择排序

基本思想:第i 趟在n-i+1(i=1,2,…,n-1)个记录中选取关键码最小的记录作为有序序列中的第i个记录。

样例展示:

12 5 9 20 6 31 24
5 [12 9 20 6 31 24]
5 6 [9 20 12 31 24]
5 6 9 [20 12 31 24]
5 6 9 12 [20 31 24]
5 6 9 12 20 [31 24]
5 6 9 12 20 24 31

//选择排序
void SelectSort(int a[],int n)
{
	for(int i=0;i<n-1;i++)
	{
		int index=i;
		int j;
		for(j=i+1;j<n;j++)
			if(a[j]<a[index])
				index=j;
		if(index!=i) swap(a[index],a[i]);
 
	}
}

输入的问题

带空格输入一行

char s[100];
gets(s);

string s;
getline(cin, s);

输出占几位

printf("%4d%-4d",n,k);
// -:左对齐

随笔记忆_汉明距离_04

杨辉三角形

随笔记忆_汉明距离_05

不知道规律的时候的做法

#include<stdio.h>
#include<string.h>
int a[15][25];
int main()
{
    int n;
    scanf("%d",&n);
    int mid = n;
    a[1][mid] = 1;
    for(int i = 2; i <= n; i ++)
    {
        int cha = 1;
        if(i & 1)
        {
            cha = 2;
            a[i][mid] = a[i - 1][mid - 1] + a[i - 1][mid + 1];
        }

        for(int j = 1; j <= i / 2; j ++)
        {
            a[i][mid - cha] = a[i - 1][mid - cha- 1] + a[i - 1][mid - cha + 1];
            a[i][mid + cha] = a[i - 1][mid + cha- 1] + a[i - 1][mid + cha + 1];
            cha += 2;

        }
    }


    for(int i = 1; i <= n; i++)
    {
        
        for(int j = 1; j < n - i + 1; j++)
            printf(" ");
        for(int j = 1; j <= 2 * n - 1; j++)
            if(a[i][j])
                printf("%4d",a[i][j]);
        printf("\n");
    }

    return 0;
}

知道规律之后的做法

组合数的两种求法

  1. 随笔记忆_汉明距离_06
  2. 递推,a[i][j] = a[i - 1][j - 1] + a[i - 1][j];
#include<stdio.h>
#include<string.h>
int a[15][25];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i = 0; i <= n; i++)
        for(int j = 0; j <= i; j++)
            if(!j) a[i][j] = 1;
            else a[i][j] = a[i - 1][j - 1] + a[i - 1][j];



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

        for(int j = 1; j < n - i + 1; j++)
            printf(" ");
        for(int j = 1; j <= i; j++)
                printf("%4d",a[i - 1][j - 1]);
        printf("\n");
    }

    return 0;
}

代码错误:

  1. stage函数出错,位置不对,返回类型不对
  2. 输出格式不对
#include<stdio.h>
int stage(int a)
{

    int base = 1;
    for(int i = 1; i <= a; i++)
    {
        base = i * base;
    }
    return base;
}
void pyramid(int n)
{
   int line, space, yhnum;
   int x;

    for (line = 1; line <= n; line ++)
    {
       for(space = n - line ; space > 0; space--)
       {
           printf(" ");
       }
       for(yhnum = 1;yhnum <= line; yhnum++)
       {

         x = stage(line - 1 )/(stage(line  - yhnum) * stage(yhnum - 1));
         printf("%4d",x);
       }
       printf("\n");
    }
}

int main()
{
    int n;

    scanf("%d", &n);
    pyramid(n);
    return 0;
}