码迷,mamicode.com
首页 > 编程语言 > 详细

[算法导论]#3 循环不变式

时间:2020-03-31 01:04:46      阅读:111      评论:0      收藏:0      [点我收藏+]

标签:line   str   article   htm   面试   key   ==   很多   存在   

在面试某手的时候,完成了一个有序链表的合并,之后面试官又要求用循环不变式来证明算法的正确性……循环不变式?这是啥

后来发现这是算法导论第一章的内容。

不会=算法导论没看

分析过程

必须证明三条性质

  • 初始化:循环的第一次迭代之前,它为真
  • 保持:如果循环的某次迭代之前它为真,那么下次迭代之前它仍为真
  • 终止:在循环终止时,不变式为我们提供了一个有用的性质,该性质有助于证明算法是正确的

前两步有点类似于数学归纳法,而最后一步其实也很重要,因为算法并不是无穷无尽的,必须要终止。例如二分,终止条件非常重要。

以插入排序为例

for(i = 2;i <= n;++i){
    key = a[i];
    j = i - 1;
    while(j > 0 && a[j] > key){
        a[j+1] = a[j];
        j--;
    }
    a[j] = key;
}

在一个有序的数列里插入一个数,插到正确的位置同时比它大的后移,就是这个算法的思想

那就按照循环不变式这个算法的正确性

  • 初始化:很明显在循环之前\((i<2)\)第一个数是单独的,肯定有序
  • 保持:这个算法会将比key大的数都往右移动一个位置,然后将key插入到正确的位置中,这时数组1-i是有序的。
  • 终止:循环结束后,\(i=n+1\)因此保证了1-n是有序的,每个元素都是a中原先的元素,但是拍好序了。因此算法正确。

这个证明不是太数学,而是比较感性的,但也可以说明问题

以二分为例

之前说过,一个二分算法的正确性,终止条件很重要

https://www.cnblogs.com/smallocean/p/11913963.html 这是之前做过二分的笔记

  • 在单调递增序列\(a\)中查找$\geq x $的数中最小的一个
  while(l<r){
      int mid = (l+r)>>1;/*右移运算 相当于除2并且向下取整*/
      if(a[mid]>=x) r=mid;
      else l=mid+1;
  }
  return a[l];
  1. 初始化:待查数组范围是\(l(1)-r(n)\),待查元素key如果存在必定在该范围内
  2. 保持:当符合题意时,范围变成\(l...mid\);当不符合题意时,范围变成\(mid+1...r\);这是对的
  3. 终止:什么时候停止呢?如果\(l=2,r=3\)mid会取\(l\)如果mid满足题意,会导致\(l==r\),这时应该终止,找到答案了。否则,也会导致\(l==r\)。所以终止条件就是\(l\geq r\)的时候
  • 在单调递增序列\(a\)中查找\(\leq x\)的数中最大的一个
  while(l<r){
      int mid = (l+r+1)>>1;
      if(a[mid]<=x) l=mid;
      else r=mid-1;
  }
  return a[l];
  1. 初始化:待查数组范围是\(l(1)-r(n)\),待查元素key如果存在必定在该范围内
  2. 保持:当符合题意时,范围变成\(mid...r\);当不符合题意时,范围变成\(mid+1...r\);这是对的
  3. 终止:如果\(l=2,r=3\)mid会取\(r\),如果mid满足题意,会导致\(l==r\),这时应该终止,找到答案了。否则,也会导致\(l==r\)。所以终止条件就是\(l\geq r\)的时候。如果说依然是(l+r)>>1那么会取到\(l\),如果\(l\)满足,那么将陷入死循环。

有一篇总结很好的文章:https://blog.csdn.net/ltyqljhwcm/article/details/52772002

总结

总的来说循环不变式是一个很好的思想,能帮助我们证明算法的正确性。前两步的类似数学归纳的方法和终止时候的正确性,其实在平时写代码的时候也会不经意间用到类似的方法来想。这次把这种思路书面化,以后也不会再走很多弯路了。

[算法导论]#3 循环不变式

标签:line   str   article   htm   面试   key   ==   很多   存在   

原文地址:https://www.cnblogs.com/smallocean/p/12602356.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!