算作自己的一次复习

排序

冒泡排序

C语言

#include <stdbool.h>
#include <stdio.h>

#define GET_ARRAY_LEN(array, len) {len = (sizeof(array) / sizeof(array[0]));}

void bubbleSort(int a[], int count) {
    int index, temp;
    bool flag = true;

    for (index = 1; index <= count; index++) {
        for (int pos = 0; pos < count - index; pos++) {
            if (a[pos] > a[pos + 1]) {
                temp = a[pos];
                a[pos] = a[pos + 1];
                a[pos + 1] = temp;
                flag = false;
            }
        }
        if (flag) {
            break;
        }
    }
}

void main() {
    int a[] = {1, 2, 323423, 234, 43652, 234, 24, 6457, 7457, 35, 23};
    int len;
    GET_ARRAY_LEN(a, len);

    bubbleSort(a, len);
    for (int i = 0; i < len; i++) {
        printf("%d ", a[i]);
    }
}

python

#!/usr/bin/python
# -*- coding: utf-8 -*-

def bubble_sort(r_list):
    flag = True
    for index in range(len(r_list)-1, 0, -1):
        if flag:
            flag = False
            for i in range(index):
                if r_list[i] > r_list[i+1]:
                    r_list[i], r_list[i+1] = r_list[i+1], r_list[i]
                    flag = True
                  
if __name__ == '__main__':
    test_list = [4, 6, 9, 11, 3, 2, 0]
    bubble_sort(test_list)
    print test_list                  

插入排序

python 递归版本

def insert_sort(r_list):
    r_len = len(r_list)
    if r_len > 1:
        r_list = insert_sort(r_list[:r_len-1]) + [r_list[-1]]
    else:
        return r_list

    i = r_len - 1
    while i > 0:
        j = i - 1
        if r_list[j] > r_list[i]:
            r_list[i], r_list[j] = r_list[j], r_list[i]

        i -= 1

    return r_list
    

python another version

def insert_sort(r_list, r_len=None):
    if r_len is None:
        r_len = len(r_list)
    if r_len > 1:
        insert_sort(r_list, r_len-1)
    else:
        return

    i = r_len - 1
    j, temp = i, r_list[i]
    while j > 0 and temp < r_list[j-1]:
        r_list[j] = r_list[j-1]
        j -= 1
    r_list[j] = temp

堆排序

使用官方库

import heapq
data = [9, 3, 5, 7, 2, 4, 6, 8, 0]
result = []

heapq.heapify(data)
while data:
    result.append(heapq.heappop(data))
    
return result

自己写

def heap_adjust(heap, i, h_len):
    while 2 * i + 1 < h_len:
        child = 2 * i + 1
        if child + 1 < h_len:
            if heap[child] < heap[child + 1]:
                child += 1

        if heap[i] < heap[child]:
            heap[i], heap[child] = heap[child], heap[i]
            i = child
        else:
            break


def heap_sort(heap):
    n = len(heap)
    for x in reversed(xrange(n // 2)):
        heap_adjust(heap, x, n)

    for y in xrange(n-1, 0, -1):
        heap[0], heap[y] = heap[y], heap[0]
        heap_adjust(heap, 0, y)

快速排序

def qsort(L):
    if len(L) <= 1: return L
    return qsort([lt for lt in L[1:] if lt < L[0]]) + [L[0]] + qsort([ge for ge in L[1:] if ge >= L[0]])

线性排序

主要有计数排序、桶排序和基数排序,均为稳定算法

查找

查找数组中的最大值和最小值

思路:

  1. 数组中的元素每两个进行一组一次比较,较大元素放到大元素表中,较小元素放到小元素表中,分组的复杂度n/2

  2. 在小元素表中逐个比较找到最小值即整个数组的最小值,复杂度n/2;在大元素表中逐个比较找到最大值,即数组的最大值,复杂度也是n/2

总的复杂度3n/2,代码如下

def find_max_and_min(r_list):
    r_len = len(r_list)
    if r_len < 1:
        return (None,) * 2

    if r_len % 2 == 0:
        start = 2
        max_item, min_item = r_list[0], r_list[1]
        if max_item < min_item:
            max_item, min_item = min_item, max_item
    else:
        max_item, min_item = (r_list[0],) * 2
        start = 1

    while start < r_len:
        min_test, max_test = r_list[start], r_list[start + 1]
        if min_test > max_test:
            min_test, max_test = max_test, min_test

        if min_test < min_item:
            min_item = min_test
        if max_test > max_item:
            max_item = max_test

        start += 2

    return max_item, min_item

二分查找

使用官方库

from bisect import bisect_left

def binary_search(a, x, low=0, high=None):   
    high = high if high is not None else len(a) # hi defaults to len(a)   
    pos = bisect_left(a, x, low, high)          
    return (pos if pos != high and a[pos] == x else -1)

自己写

def binary_search(r_list, target):
    low, high = 0, len(r_list)
    while low <= high:
        mid = (low + high) // 2
        if r_list[mid] == target:
            return mid
        elif r_list[mid] > target:
            high = mid - 1
        else:
            low = mid + 1

    return -1

用递归写

def binary_search(r_list, target, low=0, high=None):
    if high is None:
        high = len(r_list)

    if low <= high:
        mid = (low + high) // 2
        mid_val = r_list[mid]
        if mid_val == target:
            return mid
        elif mid_val > target:
            return binary_search(r_list, target, low, mid-1)
        else:
            return binary_search(r_list, target, low+1, high)
    else:
        return -1

链表

反转单链表

主要设置好变量,这个不难,所以一般会要求写得快又准

class Node(object):
    def __init__(self, data=None):
        self.data = data
        self.next = None


def reverse(r):
    if r.next is None:
        return r

    head = r
    cur = r.next
    tail = r  # new linked node tail, will return as new head
    while cur:
        tmp = cur.next
        head.next = tmp
        cur.next = tail
        tail = cur
        cur = tmp

    return tail


def print_node(x):
    link_list = []
    while x:
        link_list.append(x.data)
        x = x.next

    print ' -> '.join(map(str, link_list))


def main():
    a = Node(1)
    a.next = Node(2)
    a.next.next = Node(3)

    print_node(a)
    print

    b = reverse(a)
    print_node(b)


if __name__ == '__main__':
    main()

字符串

最长公共子串

代码来自英文维基,原理是构造矩阵,找最长的对角线连续不为0的长度

def longest_common_substring(s1, s2):
    m = [[0] * (1 + len(s2)) for i in xrange(1 + len(s1))]
    longest, x_longest = 0, 0
    for x in xrange(1, 1 + len(s1)):
        for y in xrange(1, 1 + len(s2)):
            if s1[x - 1] == s2[y - 1]:
                m[x][y] = m[x - 1][y - 1] + 1
                if m[x][y] > longest:
                    longest = m[x][y]
                    x_longest = x
            else:
                m[x][y] = 0
    return s1[x_longest - longest: x_longest]

最长公共子序列

不要求字符是连续的,下面解法有最大递归1000的限制,所以还是使用自顶向上的DP更好一点,有兴趣可以看这里

def memoize(fn):
    cache = dict()
    def wrapped(*v):
        key = tuple(v) # tuples are hashable, and can be used as dict keys
        if key not in cache:
            cache[key] = fn(*v)
        return cache[key]
    return wrapped

def lcs(xs, ys):
    @memoize
    def lcs_(i, j):
        if i and j:
            xe, ye = xs[i-1], ys[j-1]
            if xe == ye:
                return lcs_(i-1, j-1) + [xe]
            else:
                return max(lcs_(i, j-1), lcs_(i-1, j), key=len)
        else:
            return []
    return lcs_(len(xs), len(ys))

最大子序列

待续

排列与组合

组合

通常的实现是10置换法

def combinations(iterable, r):
    # combinations('ABCD', 2) --> AB AC AD BC BD CD
    # combinations(range(4), 3) --> 012 013 023 123
    pool = tuple(iterable)
    n = len(pool)
    if r > n:
        return
    indices = range(r)
    yield tuple(pool[i] for i in indices)
    while True:
        for i in reversed(range(r)):
            if indices[i] != i + n - r:
                break
        else:
            return
        indices[i] += 1
        for j in range(i+1, r):
            indices[j] = indices[j-1] + 1
        yield tuple(pool[i] for i in indices)

排列

其实就是将组合得到的每个分组进行全排列

def permutations(iterable, r=None):
    # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
    # permutations(range(3)) --> 012 021 102 120 201 210
    pool = tuple(iterable)
    n = len(pool)
    r = n if r is None else r
    if r > n:
        return
    indices = range(n)
    cycles = range(n, n-r, -1)
    yield tuple(pool[i] for i in indices[:r])
    while n:
        for i in reversed(range(r)):
            cycles[i] -= 1
            if cycles[i] == 0:
                indices[i:] = indices[i+1:] + indices[i:i+1]
                cycles[i] = n - i
            else:
                j = cycles[i]
                indices[i], indices[-j] = indices[-j], indices[i]
                yield tuple(pool[i] for i in indices[:r])
                break
        else:
            return

这两段代码里都用到了for...else的语句结构,return放不放在else下的区别是,当for循环里break时,可以跳过return,否则必须经过return。当经过完所有for的条件后,将会返回
这两段代码的结果都是字典序由小到大


quietin
761 声望44 粉丝

兴趣在程序语言, 高性能, 分布式等方面


引用和评论

0 条评论