手撕 part1

1、宏定义三个数最大值

挺有意思
max((a), (b), (c)) (a) > (b)? ((a) > (c)? (a) : (c)) ((b) > (c)? (b) : (c))

2、排序算法稳定性

什么是稳定? 稳定指:相同大小的值,经过排序后相对位置不变。
不稳定的常见排序算法:“快些选队”(快速排序,希尔排序,选择排序,堆排序)。
堆排序为什么不稳定?自己举例子。

3、基数排序

void count_sort(int num[], int n, int fac){
    int cnt[10] = {0};
    int* temp = new int[n + 1];
    for(int i = 0; i < n; i++) cnt[num[i] / fac % 10]++;
    for(int i = 1; i < 10; i++) cnt[i] += cnt[i - 1];
    for(int i = n - 1; i >= 0; i--){
        temp[cnt[num[i] / fac % 10] - 1] = num[i];
        cnt[num[i] / fac % 10]--;
    }
    for(int i = 0; i < n; i++) num[i] = temp[i];
    delete[] temp;
}

void radix_sort(int num[], int n){
    int Max = num[0];
    for(int i = 0; i < n; i++) Max = max(Max, num[i]);
    for(int i = 1; Max / i; i *= 10){
        count_sort(num, n, i);
    }
}

4、链表相关

判断链表有环:
空间复杂度O(1)的解法:快慢指针。
快指针每次走2步,慢指针每次走1步,当他们第一次相遇时,说明有环。
证明:
假设环大小R,当慢指针到环入口时,快慢指针相距S。不妨设t时间后两者相遇,则必须有S+2t=t+nR。化简可得S+t=nR,因为S<R,所以必有解t=R-S。故假设成立,快慢指针可行。

链表环入口:
快指针每次走2步,慢指针每次走1步,当他们第一次相遇后,设置两个慢指针,一个从相遇点开始,一个重新从点开始,再次相遇就是入口。
证明:
假设环大小R,起点到入口长度L,入口到相遇点S,那么可得2(L+S)=L+S+nR,简化得L+S=nR。所以L=nR-S,nR-S可以看成从相遇点开始走n圈然后回退S步走到入口,L为从起点走到入口,那么显然在入口相遇。

找到链表中点:
空间复杂度O(1)的解法:快慢指针。
快指针每次走2步,慢指针每次走1步。快指针走到末尾时,慢指针在中间。

5、二进制数1

暴力、lowbit

参考资料

每天一道LeetCode-----判断链表是否有环,如果有,找到环的入口位置

posted @ 2020-07-16 23:39  KirinSB  阅读(174)  评论(0编辑  收藏  举报