编程珠玑-笔记1

来源:互联网 发布:2017最新网络神曲 编辑:程序博客网 时间:2024/05/22 02:30

为什么要自己造轮子

Ex:怎样给一个磁盘文件排序?
不同的排序条件,比如待排序大小,可提供的内存空间不同,都会使程序不同,所以我们不能盲目的使用系统提供的排序功能
所以对小问题的仔细分析有时可以得到明显的实际益处。
程序的一般原理:

  1. 正确的问题
  2. 位图数据结构
  3. 多趟算法
  4. 时间-空间折中与双赢
  5. 简单的设计

算法的重要性

三个问题

1、给定一个包含32位整数的顺序文件,它至多只能包含40亿个这样的整数,并且整数的次序是随机的。请查找一个此文件中不存在的32位整数。在有足够内存的情况下,你会如何解决这个问题?如果你可以使用若干外部临时文件但可用主存却只有上百字节,你会如何解决这个问题?
如果内存足够可以使用,位图技术(每一位代表一个数)
如果内存不够可以使用,二分搜索

2、将一个具有n个元素的一维向量向左旋转i个位置。例如,假设n=8,i=3,那么向量abcdefgh旋转之后得到向量defghabc。你只能使用1字节的辅助变量。
方法1:块变换
旋转向量实际就是交换xy的两段,x(abc),y(defgh)。将y分为两段yl(de),yr(fgh)。交换x和yr,也就是将xylyr转换成yrylx。这时x已经处于正确的位置,然后再递归的处理b的两部分即可。(程序较复杂)
方法2:分别反向(leetcode 189. Rotate Array)
reverse(0,i-1); //abcdefgh
reverse(i,n-1); //cbahgfed
reverse(0,n-1); //defghabc
3、给定一本英语单词词典,请找出所有的变位词集。例如,因为”pots” “stop” “tops”相互之间都是由另一个词的各个字母改变序列而构成的,因此这些词相互之间就是变位词。
(leetcode 49. Group Anagrams)
如何思考:使这些变位词集合具有相同的标识,然后再集合
1、标识:排序后的单词
2、将所有的单词按照其标识排序
Code:

class Solution {public:    vector<vector<string>> groupAnagrams(vector<string>& strs) {        vector<vector<string>> res;        unordered_map<string,vector<string>> hash;        for(int i=0;i<strs.size();i++)        {            string s=strs[i];            sort(s.begin(),s.end());            hash[s].push_back(strs[i]);        }        unordered_map<string,vector<string>>::iterator it=hash.begin();        for(;it!=hash.end();it++)            res.push_back(it->second);        return res;    }};

数据决定程序结构

好的数据结构可以使程序短小、清晰、漂亮。
思考数据的几条原则:

  • 使用数组重新编写重复代码
    冗长的相似代码常常可以使用最简单的数据结构–数组来更好地表述
  • 封装复杂结构
    当需要非常复杂的数据结构时,使用抽象术语进行定义,并将操作表示为类
  • 尽可能使用高级工具
    超文本、名字-键值、电子表格、数据库,编程语言等都是特定问题领域中的强大的工具。
  • 从数据得出程序的结构
    通过使用恰当的数据结构来替代复杂的代码,从数据可以得出程序的结构。

编写正确的程序

  1. 问题定义
  2. 算法设计
  3. 数据结构的选择

Ex:编写二分搜索的程序

//递归方法int Binary_Search_Recursion(vector<int> v, int begin, int end, int key){    if (begin > end)        return -1;    int mid = (begin + end) >> 1;    if (v[mid] > key)        return Binary_Search_Recursion(v, begin, mid - 1, key);    else if (v[mid] < key)        return Binary_Search_Recursion(v, mid + 1, end, key);    else        return mid;}//非递归方法int Binary_Search(vector<int> v, int begin, int end, int key){    if (begin > end)        return -1;    int mid = 0;    while (begin <= end)    {        mid = (begin + end) >> 1;        if (v[mid] > key)            end = mid - 1;        else if (v[mid] < key)            begin = mid + 1;        else            return mid;    }    return -1;}

如何调试

1、学会打断点
2、计时
C/C++中的计时函数是clock(),而与其相关的数据类型是clock_t
在time.h文件中,还定义了一个常量CLOCKS_PER_SEC,它用来表示一秒钟会有多少个时钟计时单元,其定义如下:
#define CLOCKS_PER_SEC ((clock_t)1000)
可以看到每过千分之一秒(1毫秒),调用clock()函数返回的值就加1。
Test code:

int main(){    vector<int> data = { 1, 2, 3, 4, 5, 6, 7 };    clock_t start;    clock_t finish;    start = clock();    int a1 = Binary_Search(data, 0, data.size() - 1, 1);    int b1 = Binary_Search(data, 0, data.size() - 1, 7);    int c1 = Binary_Search(data, 0, data.size() - 1, 10);    finish = clock();    cout << (double)(finish - start) / CLOCKS_PER_SEC << endl;    return 0;}
0 0
原创粉丝点击