学习编程艺术的心得、知识总结1(长期更新)
2015-06-16 11:59
337 查看
本文章用于记录阅读七月大神的博客编程艺术的心得、知识,在看了两三章节的过程中,每次都是先看思路,自己编写调试后和他的代码对比,在自己编写过程中,发现了自己对编程知识方法的许多错误使用,同时学习到了简洁的编程方式。在整个阅读过程,想到遇到什么都记录一下,在反思中学习进步!!
七月的编程艺术github版网址:https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/Readme.md。
1、对string类型的变量a使用sort排序:
结果发现运行出错。原因是,str指针已经被赋值了,在str++的过程中,str始终不为一个空指针,while循环的判断条件一直成立,因此出错。此时,参考博客,将while判断改为*str==0即可,即指针指向的值为0。
知识点:
设置int型数的最大值和最小值,用位运算实现如下:
当实现函数的参数形式如下时:
字符串用字符指针s来表示的,此时用两个指针指示首尾,依次改变指针指向进行比较。此时对两个指示指针赋值如下:
error C2440: '=' : cannot convert from 'const char *' to 'char *'
在网上查找解决办法是进行强制转化,修改如下:
在看到题目后,想到以前做过的一个深度优先遍历题目,此题也可使用此思路,从a开始查找到b再到底部c返回一条路径,然后向上返回,查找到c再到b。然后返回到最开始,从b开始查找。
下面是基于此深度搜索的实现代码:
而作者文中的递归实现,使用了交换操作,勉强理解了,感觉实现有点复杂。
第二种方法是基于字典序排列,即使用了STL中的next_permutation算法思想来实现的,再往后的实现中,可直接循环调用此函数来实现全排列,可大大简化代码,下面用此函数实现字符串的全排列如下:
五、最小的K个数
其中使用堆来维护K个数的集合还没实现,因为一直以来对堆就很陌生,所以没实现。下面是直接根据快速选择思路实现的代码:
七月的编程艺术github版网址:https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/Readme.md。
一、字符串包含
知识点:1、对string类型的变量a使用sort排序:
sort(a.begin(),a.end());2、算法的位运算实现,比较经典,对位操作比较陌生,代码记录在此,方便随时学习。
// “最好的方法”,时间复杂度O(n + m),空间复杂度O(1) bool StringContain(string &a,string &b) { int hash = 0; for (int i = 0; i < a.length(); ++i) { hash |= (1 << (a[i] - 'A')); } for (int i = 0; i < b.length(); ++i) { if ((hash & (1 << (b[i] - 'A'))) == 0) { return false; } } return true; }
二、字符串转换为整数
按照最初的想法,直接读取字符串中的一个,然后转为数字,然后以num=num*10+m更新即可,自己写了如下的函数来实现。int StrToInt1(const char *str) { int num=0; while(str) { int m=*str-'0'; num=num*10+m; str++; } return num; }
结果发现运行出错。原因是,str指针已经被赋值了,在str++的过程中,str始终不为一个空指针,while循环的判断条件一直成立,因此出错。此时,参考博客,将while判断改为*str==0即可,即指针指向的值为0。
知识点:
设置int型数的最大值和最小值,用位运算实现如下:
static const int MAX_INT = (int)((unsigned)~0 >> 1); static const int MIN_INT = -(int)((unsigned)~0 >> 1) - 1;
三、回文判断
当实现函数的参数形式如下为string类型时:bool palind(string *s, int n)此时直接看成数组,设定i从0到s.length()/2即可。
当实现函数的参数形式如下时:
bool palind(const char *s, int n)
字符串用字符指针s来表示的,此时用两个指针指示首尾,依次改变指针指向进行比较。此时对两个指示指针赋值如下:
char *first,*last; first=s; last=s+n-1;结果出现了如下错误:
error C2440: '=' : cannot convert from 'const char *' to 'char *'
在网上查找解决办法是进行强制转化,修改如下:
char *first=(char *)s; char* last=(char *)(s+n-1);
四、字符串全排列
输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则输出由字符a、b、c 所能排列出来的所有字符串abc、acb、bac、bca、cab 和 cba。在看到题目后,想到以前做过的一个深度优先遍历题目,此题也可使用此思路,从a开始查找到b再到底部c返回一条路径,然后向上返回,查找到c再到b。然后返回到最开始,从b开始查找。
下面是基于此深度搜索的实现代码:
#include<iostream> #include<string> using namespace std; string a="abcd"; int lu[4]; //保存路径 int rest[4];//剩余未访问的字符 int j=0,restone_temp=-1; //j为路径计数,restone_temp为剩余一个未访问时,此未访问节点的下标,
<span style="white-space:pre"> </span>//因为剩余一个未访问时,路径已经确定,此设置方便返回到上一步选择的节点 bool restone() //判断是否剩余一个未访问 { int count=0; int k=-1; for(int i=0;i<a.length();i++) { if(rest[i]==1) { count++; k=i; } } if(count==1) { restone_temp=k; //记录还有一个未访问时,此节点的下标 return true; } else return false; } void strsort() { if(restone()) //剩余一个即确定了组合方式,打印结果 { for(int i=0;i<a.length()-1;i++) cout<<a[lu[i]]; cout<<a[restone_temp]; cout<<endl; return; } for(int i=0;i<a.length();i++) { if(rest[i]) { rest[i]=0; lu[j++]=i; strsort(); //递归 rest[i]=1; //返回上一步选择的节点,如果访问到最后一个才返回,需要向上返回两次, j--;<span style="white-space:pre"> </span>//但返回两次时,向上返回的节点难以确定 } } } int main() { for(int i=0;i<a.length();i++) rest[i]=1; strsort(); return 0; }(⊙﹏⊙)汗。。检查了一下代码,发现上述的代码判断剩余一个未访问的操作完全多余,在递归过程中,在向上返回一次时,因为没有其他路径可走,又会自动向上返回一次,因此上述代码严重冗余。对深度搜索的递归实现认识还不足,需要进一步学习。改进的代码如下:
#include<iostream> #include<string> using namespace std; string a="abcd"; int lu[4]; int rest[4]; int j=0; bool norest() //判断是否所有点已经被访问 { for(int i=0;i<a.length();i++) { if(rest[i]==1) return false; } return true; } void strsort() { if(norest()) //所有点被访问,打印路径 { for(int i=0;i<a.length();i++) cout<<a[lu[i]]; cout<<endl; return; } for(int i=0;i<a.length();i++) { if(rest[i]) { rest[i]=0; lu[j++]=i; strsort(); rest[i]=1; j--; } } } int main() { for(int i=0;i<a.length();i++) rest[i]=1; strsort(); return 0; }
而作者文中的递归实现,使用了交换操作,勉强理解了,感觉实现有点复杂。
第二种方法是基于字典序排列,即使用了STL中的next_permutation算法思想来实现的,再往后的实现中,可直接循环调用此函数来实现全排列,可大大简化代码,下面用此函数实现字符串的全排列如下:
#include<iostream> #include<string> #include <algorithm> using namespace std; int main() { char ch[200]; cin>>ch; sort(ch,ch+strlen(ch)); do{ cout<<ch<<endl; }while(next_permutation(ch, ch+strlen(ch))); return 0; }思考题中,已知字符串里的字符是互不相同的,现在任意组合,比如ab,则输出aa,ab,ba,bb,作者提供的解决方法非常巧妙,也是基于递归实现的,记录在此:
#include<iostream> #include<string> #include <algorithm> using namespace std; void perm(char* result, char *str, int size, int resPos) { if(resPos == size) printf("%s\n", result); else { for(int i = 0; i < size; ++i) { result[resPos] = str[i]; perm(result, str, size, resPos + 1); } } } int main() { char ch[200]; cin>>ch; sort(ch,ch+strlen(ch)); char result[200]={0}; perm(result,ch,strlen(ch),0); return 0; }
五、最小的K个数
其中使用堆来维护K个数的集合还没实现,因为一直以来对堆就很陌生,所以没实现。下面是直接根据快速选择思路实现的代码:
#include<iostream> #include<algorithm> using namespace std; int median3(int a[],int first,int last) { int midium=(first+last)/2; if(a[first]>a[midium]&&a[first]>a[last]) { if(a[midium]>a[last]) return midium; else return last; } if(a[first]<a[midium]&&a[first]<a[last]) { if(a[midium]<a[last]) return midium; else return last; } return first; } void quickselect(int s[],int first,int last,int k) { int m=0,n=0; int piv=0; int s1[100],s2[100]; piv=median3(s,first,last); for(int i=0;i<=last;i++) { if(s[i]>=s[piv]) { s2[n++]=s[i]; } else s1[m++]=s[i]; } if(k>m) { for(int j=first;j<n;j++) cout<<s1[j]<<" "; quickselect(s2,0,n-1,k-m); } else if(k<m) quickselect(s1,0,m-1,k); else { for(int j=first;j<m;j++) cout<<s1[j]<<" "; cout<<endl; } } int main() { int arr[100]={462359,161047,2346,716099,189159,264108,905891,115240,473403,221514, 723403,684465,257361,34611,535903,478932,345173,117798,693203,593953}; quickselect(arr,0,19,10); return 0; }
相关文章推荐
- php对gzip文件或者字符串解压实例参考
- 实现会员管理的会员升级规则窗体功能代码(二十一)
- Java compiler level does not match解决方法
- C#WinForm控件使用
- ruby实现网页图片抓取
- MyEclipse 2015 CI
- python virtualenv
- java中堆和栈的区别
- C#自动判断Excel版本使用不同的连接字符串
- 浅谈ASP.NET中多层架构
- Java反射教程
- spring事务源码分析结合mybatis源码(三)
- [学习笔记]stringByReplacingOccurrencesOfString返回值的两种情况
- Java使用Fork/Join框架来并行执行任务
- Java 过滤特殊字符
- C#打印类PrintDocument、PrintDialog、PrintPreviewDialog使用示例
- Qt数据库 QSqlTableModel实例操作
- ASP.NET MVC 4 (十三) 基于表单的身份验证
- java正则表达式,将字符串中\后的第一个字母变成大写
- C#实现获取设置IP地址小工具