摘要: 可以算作是一道谜语题第一步仍然使用快慢指针法,找到第一次相遇点。第二步设两个指针,一个从相遇点出发,另一个从原始起点出发,二者都是一次一步,当二者相遇时,所在的点即为环的入口.第二步要会从数学上证明:设进入环之前的直线距离为d,二者相遇时,慢指针在环上走过的距离是x,快指针绕环k(注意k必然>=1)圈外加x, 环的周长是C,则有: d+x = (x+d+kC) / 2 => d+x = kC =>d = (k-1)C+(C-x)因此,第二步中,从起点出发的指针走过d时,从相遇点出发的的指针走过(k-1)C +(C-x),而C-x恰好是回到入口点出的长度,于是得证。/** * 阅读全文
posted @ 2014-03-23 20:38 苏卡达 阅读(110) 评论(0) 推荐(0)
摘要: 快慢指针法检查单链表是否存在环,注意判断无环的条件。/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */class Solution {public: bool hasCycle(ListNode *head) { ListNode* dummy = new ListNode(0); dummy->next = h... 阅读全文
posted @ 2014-03-23 19:55 苏卡达 阅读(148) 评论(0) 推荐(0)
摘要: 又是一道单链表相关的题目。一开始没有思路,借鉴了高手们的博客,于是采用:1.先找链的近似中间点,从中间点把链切为两段;2.翻转后半段的链;3.将后半段链按题目要求插入前半段链;需要注意的是指针的非空检查。特别强调,如果调用p->next或对其赋值,一定要保证p!=NULL.还有一些关键语句的次序一定不要搞错,之前多次出现程序写好后修改时,将break语句或者p->next=NULL(切割链)语句写的位置靠前或者靠后的情况,导致出错。/** * Definition for singly-linked list. * struct ListNode { * int val; * .. 阅读全文
posted @ 2014-03-23 17:09 苏卡达 阅读(168) 评论(0) 推荐(0)
摘要: 使用直接插入排序。值得考虑的是,是否可以使用二分搜索的插入排序?希望有实现了的朋友告诉我。几道链表类题目做下来,总结出两个技巧:1.对没有头结点的链表,首先建立伪头结点dummy,这样一来,当算法需要始终维护一个当前指针的父结点指针pre时,就不至于因为在初始时将父结点pre置为NULL而出错。2.一步两步方法,可以较快的找到链表的近似中间点的指针;如果使用先遍历整个链表确定长度,在遍历半个链表长度找到中间点的方法,时间复杂度为O(1.5N),而如果同时使用两个指针p1和p2,p1每次移动一步而p2每次移动2步,当p2达到尾部时p1大约位于链表中间点附近,这样做时间复杂度为O(N);代码示意: 阅读全文
posted @ 2014-03-23 15:44 苏卡达 阅读(128) 评论(0) 推荐(0)
摘要: 波兰式:将四则运算的表达式解析成一棵二叉树,后续遍历之,得到的字符串序列就是逆波兰式,也叫后缀表达式。一开始考虑时,首先想到建立两个栈,一个栈是数字栈,一个栈是操作符栈,但是实现了一下发现不可行,重新分析发现理论上也是错误的。考虑到后缀表达式的性质,可以很容易的确定根节点和右子树根节点(如果有的话)。四则运算表达式的二叉树的每个非叶子结点一定有两个孩子。于是考虑使用递归,即:1.找到根节点;2.如果根节点数字,则返回其值;3.如果根节点是算符op,则计算右子树值; 计算左子树值; 返回:左子树值op右子树值但是在上面的3中,左子树的根节点位置是无法再访问其根节点时确定的,解决办法就是在递归过程 阅读全文
posted @ 2014-03-23 14:07 苏卡达 阅读(235) 评论(0) 推荐(0)
摘要: 数据结构中的排序算法基本都是以顺序表为例讲解的,本题的新颖之处在于要求对单链表进行排序。首先考虑,插入排序(普通,折半)和冒泡的效率都是O(n^2),排除之;(PS: 如果有好思路请告诉我^_^)其次,剩下的只有堆排序,二路归并排序,快速排序,考虑到堆的结构是严重依赖顺序表的完全二叉树,所以放弃之;最后只剩下两种分治递归思想的排序法:快排和二路归并排序。采用二路归并排序 1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6... 阅读全文
posted @ 2014-03-23 11:12 苏卡达 阅读(140) 评论(0) 推荐(0)
摘要: 没想到非递归的先序遍历对我来说也蛮有挑战性的...基本思想是从非递归后续遍历改进而来。仍然使用栈作为临时存储区,区别是mark只有0和1两种。mark=0,代表第一次访问该结点,于是访问+左孩子进栈+mark自增1mark=1,代表第二次访问该结点,于是出栈该结点+右孩子进栈/** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right... 阅读全文
posted @ 2014-03-20 14:55 苏卡达 阅读(138) 评论(0) 推荐(0)