折半查找(二分搜索)的应用和技巧全面总结
折半查找应该算是算法中比较简单常见,但却很实用的方法之一了,又叫做二分搜索,其应用比较广泛,可以用于排序数组中元素的查找,复杂度仅为log(N),也可以用于有序数组中插入元素等等,一般而言针对排序数组的一些算法都会活多或少的用到折半查找活折半查找的思想,折半查找的实现主要分为两种方式,一种是遍历非递归形式,一种是采用递归的形式。
1、非递归形式,这种实现主要是通过每次调整中点的位置来实现。 1. int binsearch1(int arr[], int k, int l, int h){
2. if(l > h){
3. return -1;
4. }
5. int mid;
6. while(l <= h){
7. mid = (l + h) / 2;
8. if(k == arr[mid]){
9. return mid;
10. }else if(k > arr[mid]){
11. l = mid + 1;
12. }else{
13. h = mid - 1;
14. }
15. }
16. return -1;
17. }
这种方式比较灵活,而已有利于解决很多变形的问题,后面会介绍。
2、递归的形式,这种形式比较简单,调整起点,中点,终点的位置,递归函数就可以实现
1. int binsearch2(int arr[], int k, int l, int h){
2. if(l > h){
3. return -1;
4. }
5. int mid = (l + h) / 2;
6. if(k == arr[mid]){
7. return mid;
8. }else if(k > arr[mid]){
9. binsearch2(arr, k, mid +1, h);
10. }else if(k < arr[mid]){
11. binsearch2(arr, k, l, mid - 1);
12. }
13. return -1;
14. }
二、现在考虑复杂一点的二分搜索的问题,当我们遇到这样的数组a={1, 2, 3, 3, 5, 7, 8},存在重复的元素,需要从中找出3第一次出现的位置,这里3第一次出现的位置是2,《编程珠玑》里给出了很好的分析,二分搜索主要的精髓在于不变式的设计(就是上面的while循环条件式)。 1. int binsearch_first(int arr[], int k, int n){
2. int l = -1, h = n;
3. while(l + 1 != h){
4. int m = (l + h) / 2;
5. if(k > arr[m]){
6. l = m;
7. }else{
8. h = m;
9. }
10. }
11. int p = h;
12. if(p >= n || arr[p] != k){
13. return -1;
14. }
15. return h;
16. }
算法分析:设定两个不存在的元素a[-1]和a[n],使得a[-1] < t <= a[n],但是我们并不会去访问者两个元素,因为(l+u)/2 > l=-1, (l+u)/2 < u=n。循环不变式为l<u && t>a[l] && t<=a[u] 。循环退出时必然有l+1=u, 而且a[l] < t <= a[u]。循环退出后u的值为t可能出现的位置,其范围为[0, n],如果t在数组中,则第一个出现的位置p=u,如果不在,则设置p=-1返回。该算法的效率虽然解决了更为复杂的问题,但是其效率比初始版本的二分查找还要高,因为它在每次循环中只需要比较一次,前一程序则通常需要比较两次。
举个例子:对于数组a={1, 2, 3, 3, 5, 7, 8},我们如果查找t=3,则可以得到p=u=2,如果查找t=4,a[3]<t<=a[4], 所以p=u=4,判断a[4] != t,所以设置p=-1.一种例外情况是u>=n, 比如t=9,则u=7,此时也是设置p=-1.
特别注意的是,l=-1,u=n这两个值不能写成l=0,u=n-1。虽然这两个值不会访问到,但是如果改成后面的那样,就会导致二分查找失败,那样就访问不到第一个数字。如在a={1,2,3,4,5}中查找1,如果初始设置l=0,u=n-1,则会导致查找失败。
同理:查找数组中一个元素最后出现的位置如下: 1. int binsearch_last(int arr[], int k, int n){
2. int l = -1, h = n;
3. while(l + 1 != h){
4. int m = (l + h) / 2;
5. if(k >= arr[m]){
6. l = m;
7. }else{
8. h = m;
9. }
10. } 11. int p = l;
12. if(p <= -1 || arr[p] != k){
13. return -1;
14. }
15. return p;
16. }
三、旋转数组中元素的查找
什么是旋转数组呢,旋转数组就是将个一个有序数组以一个点为中心进行旋转(前后颠倒),例如{4,5 ,1,2 ,3}是{1,2,3,4,5}的一个以3为中心的旋转。这样数组就变得整体无序了,但是还是部分有序的。
第一个解决方案:
可以找到旋转的中点,然后对两个部分有序的数组分别进行二分查找
1. int split(int a[], int n)
2. {
3. for (int i=0; i<n-1; i++) {
4. if (a[i+1] < a[i])
5. return i;
6. }
7. return -1;
8. }
9.
10. int bsearch_rotate(int a[], int n, int t)
11. {
12. int p = split(a, n); //找到分割位置
13. if (p == -1)
14. return bsearch_first(a, n, t); //如果原数组有序,则直接二分查找即可
15. else {
16. int left = bsearch_first(a, p+1, t); //查找左半部分
17. if (left == -1) { //左半部分没有找到,则查找右半部分
18. int right = bsearch_first(a+p+1, n-p-1, t); //查找右半部分
19. if (right != -1) return right+p+1; //返回位置,注意要加上p+1
20. return -1;
21. }
22. return left; //左半部分找到,则直接返回
23. }
24. }
还有另外一种方法就是还按照一次二分查找的形式进行,可以这样考虑计算数组中点的时候,会将数组分为两个部分,一部分是有序的,或者两部分有序的,总之必然有一遍是有序的,那么就又可以按照二分的思想进行求解。
二分查找算法有两个关键点:1)数组有序;2)根据当前区间的中间元素与x的大小关系,确定下次二分查找在前半段区间还是后半段区间进行。
仔细分析该问题,可以发现,每次根据low和high求出mid后,mid左边([low, mid])和右边([mid, high])至少一个是有序的。
a[mid]分别与a[left]和a[right]比较,确定哪一段是有序的。
如果左边是有序的,若x<a[mid]且x>a[left], 则right=mid-1;其他情况,left =mid+1;
如果右边是有序的,若x> a[mid] 且x<a[right] 则left=mid+1;其他情况,right =mid-1;
代码如下:
1. int bsearch_rotate(int a[], int n, int t)
2. {
3. int low = 0, high = n-1;
4. while (low <= high) {
5. int mid = low + (high-low) / 2;
6. if (t == a[mid])
7. return mid;
8. if (a[mid] >= a[low]) { //数组左半有序
9. if (t >= a[low] && t < a[mid])
10. high = mid - 1;
11. else
12. low = mid + 1;
13. } else { //数组右半段有序
14. if (t > a[mid] && t <= a[high])
15. low = mid + 1;
16. else
17. high = mid - 1;
18. }
19. }
20. return -1;
21. }
四、有序数组的插入问题
其实有序数组的插入问题也可以通过二分搜索实现,只是返回值不同而已,在没找到元素的时候返回l(最左值)值就是元素应该插入的位置。
1. int binsearch1(int arr[], int k, int l, int h){
2. if(l > h){
3. return -1;
4. }
5. int mid;
6. while(l <= h){
7. mid = (l + h) / 2;
8. if(k == arr[mid]){
9. return mid;
10. }else if(k > arr[mid]){
11. l = mid + 1;
12. }else{
13. h = mid - 1;
14. }
15. }
16. return l;
17. }
五、二分思想的变形,其实二分是一种思想,不单单是应用于有序序列,可以应用于很多将序列进行划分的问题上。
第二篇:英语发音技巧全面总结
发音技巧的全面总结
发音, 技巧
发音技巧的全面总结
一、连读技巧
(1)字尾辅音+字首元音 “异性相吸”
这是地道、纯正美语的秘诀!要刻苦操练!
在意思密切相关的一组词中,如果前一个词以辅音结尾,后一个词以元音开头,这两个词有时可以连起来读,这种现象叫连读。用符号“?”表示。
1. Take?a look?at?it.
2. Forget?about?it.
3. I feel?ashamed when?I have to speak?in front?of?a lot?of people.
4. It?is not?as good?as?I had?expected.
5. There?is no doubt?about?it.
6. I will be back?in half?an?hour.
(2)相互同化
相互同化就是前后两个连在一起得音念起来不太方便,于是连在一起的两个音就互为影响而混合成一个新的、折衷的、比较好念的音,使之念起来顺口、听起来顺儿、看起来顺眼。此类同化并非是随意的,而是有规可循的。主要的变化如下:
[ s ]+[ j ]=
Don’t you miss?your family?
[ t ]+[ j ]=
I want?you to be the bestof the best.
[ d ]+[ j ]=
Would?you show me the way to the library?
Could?you do me?a favor?
(3)字尾元音+字首元音
首先我要告诉大家,中国没几个人懂这个发音秘诀!
在两个元音之间按“字尾元音”的开口读大小适当添加上微弱的半元音[w]或[j]。如果前一个词结尾的音是:/i: /或/i/在与后面的元音连续读时可加[j]音;倘若前一个音是:/u:/ /u/在与后面的元音连读时可加[w]音。
1. May?I?ask you?a question?
2. You have two?hours.
3. How?about going to my aunt for help.
二、 省力技巧(略音)
略音也称为省音,省音也就是省力(也叫不完全爆破);也是一种常见的音变现象。在自然流利的谈话中,为了说话省力,经常把一些音省掉。省音既可出现在单词内,也可出现在词与词之间。
<特别说明>美国人说英语另外的特点是:好听、偷懒、省力、经济原则。连音、略音就是这些特点的体现。 相同的两个爆破音相邻时,第一个爆破音省略,只读后面的一个爆破音。
辅音+辅音——同性相斥
在以[t][d][k][g][p]和+以辅音开始的单词时,前面的辅音发音顿息,舌头达到发音部位“点到为止”,但不送气!
在正常速度或快速的对话中,字尾有[t][d]时通常不会把[t][d]的发音清楚地念出来,而是快要念出来时,马上憋气顿息,因此字尾[d][t]的发音常常是听不到的。
I don’t-know what-to do.
略音异类爆破+异类爆破
类似的辅音如: [d]--[t];[k]-- [g];[p]--出现时,同样省前读后。
Ask-Bob-to sit-behind-me. (省略了4个音)
相同辅音+相同辅音,前一个不发音。某单词字尾是辅音,而相邻的后面单词开头也是辅音,并且词与头词尾的两个辅音相同时,在读的时候两个相同的辅音只读一个即可;也就是说省前读后。
1. I didn’t-do it. My friend-did-it.
2. What-time is our flight-tomorrow.
三、美语发音特色
在非重读音节中两个元音中间的[t]要浊化成[d]。
1. Things are getting better and better.
2. Get out of my face.
3. Stay out of this matter, please.
4. Betty bought a bit of better butter, but said she, this butter is bitter, it’ll make my batter bitter.贝蒂买了点好的黄油。但是,她说这种黄油有点苦。它把我的面糊弄苦了。
方法篇
一、经典“三最口腔肌肉训练法”
——最大声;最清晰;最快速
“三最”法就是最大声;最清晰;最快速地反复操练句子或短文以达成地道美语“脱口而出”。这是李阳疯狂英语最神奇(magical)的方法,效果卓著。
这种练习只要稍微坚持,便可出现明显效果。经过这种培训的学生根本不知道害怕讲英语,就算是在初次和外国人交流是比较紧张,但由于平常接受的是“超级激烈的”极端训练,一紧张,害怕便产生了神奇的效果:
“最大声”变成了正常的音量(normal volume);
“最快速”变成了优雅的语速(elegant speed);
“最清晰”变成了“模模糊糊”(ambiguous)的地道英语(genuine English)最高境界
二、新“三最口腔肌肉训练法”------最慢速、最夸张、最频繁。
三、一口气训练法
当美国人讲话的时候底气很足,令人羡慕!为什么呢?因为他们讲话时用的是腹腔、胸腔、喉腔、口腔、鼻腔“合五为一”所以底气十足。我们中国人讲话使用的是嘴巴,没有底气,说话时发音不饱满,力量不足。所以我们中国人要想说一口地到流利的英文,必须在“五大发音秘诀”和“三最口腔肌肉训练法”之后,再用“一口气训练法”疯狂操练。 做法很简单:你只要深呼吸,然后再一口气里尽量多读。经过一段时间的训练以后,原来需要换几次气才能读完的一句话或小短文,一口气里就能轻松读完!
调动腹部的力量
中国人习惯用嘴巴说话,显得比较“单薄”,有气无力;美国人习惯用腹部的力量说话,浑厚有力。这就是中国人说英语和英美人说英语的最大区别。
疯狂做法:平时练习英语时,尽量运动腹部的肌肉,刚开始有点别扭,坚持一下,便会产生效果。
悦耳动听在元音
英语是否好听,主要取决于元音是否饱满、到位!
口齿清晰在辅音
如果辅音发不好,元音再标准也是口齿不清!英语的辅音和中文有很大的区别,而且复杂的多!是学习发音的特大难点。 辅音主要是舌、齿、唇的相互配合。
口腔发音和喉咙发音的区别
长元音一般是通过“口腔”发出的,发声处“靠前”;而双元音和短元音则是用喉咙发出的,发音处尽量靠后。这可是一个真正的秘密。
五大发音秘诀
1. 底气十足、元音饱满
长元音拉长
鬼鬼祟祟的英文就是由鬼鬼祟祟的元音造成的!你只要把元音发饱满、到位,你的应为立刻就会说的“悦耳动听”、“底气十足”!那些英美流行歌手就是底气十足、元音饱满的典
双元音饱满到位
双元音饱满、到位;尽量用你的口形来夸张发音,尽量发泄,尽量慢;争取以最慢的速度在一口气内用拉长、饱满、到位的放纵口形把句子读完;一定要把句子中的双元音读准。最后再用正常的语速,标准、地道的一口气轻松读完。
2. 短元音急促有力
——调动腹部的力量,一收小腹,立刻纯正
4. 连音,略音
5. 咬舌头
此外,在训练口语时请注意以下几点:
1. 断续和停连
在学说话时要注意到断续和停连。停连是声音的中断和连接,俗称“气口”。如EN101课程第18周期,1-4 中的对话就是
很好的例子:
“Yes, I want a kilo of apples, please.”
“Certainly, that's 8 dollars, please.”
2. 重音
重音是什么?重音在英语中,是Stress,是一种语音现象,指的是在多音节的单字中,某个音节读得特別明显。这个被强調的音节有音调较高、声音较响亮、以及时间较长的現象。
所谓“明显”是相对的,因此,只有一个音节的字(如英语的 eye, sun等)没有重音。兩个音节必有一个是重音,兩个以上的音节有主重音,三个以上的音节可能有次重音。
英语是有重音的语言,如果把单字的重音读错,对方就可能听不懂,甚至会错意。同时,英语的单字中,有许多的重音是按它的词类而改变的,像increase (增加)作动词用时,重音在第二音节,当名词用时,重音在第一音节。这种独特的变化在中文里找不到。我们中国人说话一字一声,含义要靠四声来表达,而英语却是靠重音来表达。初学英语的中国人,往往给英语也加上四声,这也是我们前面所说的,用说第一语言的方法来学外语的例子之一。EN101 课程里的“常用单词”,“情景对话”,“儿童乐园”,和“商务学习”等部分都有发音培训,重音的位置准确而清晰。参考网站
3. 语调
语调(Intonation)是说话时的腔调。除了字面的意义外,我们很自然的用抑扬顿挫来表达所要说的真正的意思。“弦外之音”往往是靠语调来传达的。同样一句“对不起”就有多种不同的语调。这在EN101 的课程中有极好的例子。譬如,请人让路时,打喷嚏时,打哈欠时,腔调各异。英国大剧作家萧伯纳曾说,单单一个“Yes”就有50种有声表达方法,而写下来只有一种。语调用得不对容易引起误会,或令人啼笑皆非。
语调的种类
简单地说,英语有三种的语调变化:上扬语调,下降语调和“上下兼容”语调。
上扬语调 -- 在我们的课程中,第46周期1-3 里的“Can I help you?”是个问句,也是上扬语调的好例子。但上扬语调也不是仅仅用在纯问句里,有时候,在表达不可置信的请况,或反问句里也用。例如,“You mean they got married?” 下降语调 - 第31周期,3-1里有一组问句都是下降语调:
“Where has Kelly gone?”
“Where have Jane and Larry gone?”
从这些例子,我们可以看出问句未必全用上扬语调。一般来说,下降语调的用途比上扬语调为广,因为除了问句外,几乎所有的叙述,声明,命令等等的句子都用下降语调。我们的课程中这样的句子陈出不穷。
上下兼容的语调 - 第20周期,1-2中有几个问句是上下兼容的,例如:
“Smoking or non-smoking?”
“Would you like a table inside or outside?”
上下兼容的语调由说话者按当时的情况随机应变,是最灵活的一种语调。
4.节奏
节奏涉及一句话中每个字声音的长短,轻重,徐疾。每个字的长短是否一致,往往由说话人按自己的心理元素掌握着。同样几个字说得顿挫不同,轻重不同,意义也就不同。有些人说话时非但吐字不清,速度又过于急促,让人听来,觉得不知所云。同样一个人,如果把节奏放慢些,吐字虽然不清楚,倒还是能让人听得懂。口齿清晰的人,更可以利用良好的节奏感,来有效地表达自己的意思。或斩钉截铁,或娓娓道来,或激情高亢,或从容不迫,都在于说话时对节奏的掌握。 节奏感的训练宜早不宜迟,幼儿时期是培育节奏感的最佳机会。EN101在“儿童学习乐园”里特别开辟了一块“音乐天地”,用北美家喻户晓的儿歌来培养幼儿的节奏感和韵律感。在这“音乐天地”里,孩子们(和家长们)可以一面听课程里节奏鲜明的歌曲,一面对着“歌谱”跟着唱,在欢愉快乐的气氛里,渐渐的掌握了节奏感。
了解了以上的口语训练的要点,我们在听 EN101 的标准发音时,就更要用一些力气把它听准了,在听力方面,也做到“全力以赴”。学习的秘诀不在于是否用功,而在于找到方法。 Remember, study smart beats study hard. 祝你学习进步,早日掌握EN101课程中的标准发音!