刷题日期:19:0434 星期一2021年4月19日
个人刷题记录,代码收集,来源皆为leetcode
再次经过考虑,既然面试答题用什么答都无所谓
那为什么不用自己相对来说最熟悉,语言最上层的Python呢
其他的该学的基础学会就好,用Python来做剑吧
难度中等231
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
为了让您更好地理解问题,以下面的二叉搜索树为例:
我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。
特别地,我们希望可以就地完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中的第一个节点的指针。
然后发现完了,现在对Python的链表和树定义又丈二和尚摸不着头脑了,没事,慢慢来。
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势,所以应用十分广泛。
首先肯定得把树给中序遍历过一遍,这样才能实现从小到大的顺序。
常规思路肯定得用到递归。
其实要逼迫着自己向K神那样去思考,才能把题做的得心应手吧,不过那样的习惯除了培养,也离不开大量的刷题,反思,自己现在的状态还差的挺远的。
首先第一个节点得留着,因为不仅要让head来引用,而且还要在尾指针处构成循环。操作还得就地完成,说明这个操作是在递归子程序的内部实现。
每一个递归,输入的是前一个节点,构建的是双向的循环,进入的是下一个节点。
返回的,感觉没有真正理解到递归,暂时想不出来。
有点复杂,还是学习别人的思路。参考了方法一
"""
# Definition for a Node.
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
"""
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
# lambda语句中,冒号前是参数,可以有多个,用逗号隔开,
# 冒号右边的返回值。lambda语句构建的其实是一个函数对象
a, f = [], lambda r: r and (f(r.left) or a.append(r) or f(r.right))
f(root)
n = len(a)
# enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,
# 同时列出数据和数据下标,一般用在 for 循环当中。
for i, r in enumerate(a):
r.left, r.right = a[i - 1], a[i + 1 - n] #向前,向后建立指针连接
return n and a[0] or None #返回a中的第一个
要补的东西还有很多,以及py就是简洁。执行结果:通过
显示详情
执行用时:44 ms, 在所有 Python3 提交中击败了74.48%的用户
内存消耗:16 MB, 在所有 Python3 提交中击败了48.56%的用户
学习K神的解法
"""
# Definition for a Node.
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
"""
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
def dfs(cur):
if not cur: return #为空返回的写法
dfs(cur.left) #左
if self.pre: #修改前索引
self.pre.right , cur.left = cur, self.pre #构建双向链表
else: #记录头节点
self.head = cur
self.pre = cur #保存cur
dfs(cur.right) #右
if not root: return #根节点为空,返回空
self.pre = None #往前不指向吗
dfs(root) #子程序运行
self.head.left, self.pre.right = self.pre, self.head #构建循环
return self.head #返回结果
空间效率更高了,执行结果: 通过
显示详情
执行用时:56 ms, 在所有 Python3 提交中击败了12.25%的用户
内存消耗:15.7 MB, 在所有 Python3 提交中击败了90.97%的用户
typingMonkeyL5 2020-02-12
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
a, f = [], lambda r: r and (f(r.left) or a.append(r) or f(r.right))
f(root)
n = len(a)
for i, r in enumerate(a):
r.left, r.right = a[i - 1], a[i + 1 - n]
return n and a[0] or None
K神 本文解法基于性质:二叉搜索树的中序遍历为 递增序列 。将 二叉搜索树 转换成一个 “排序的循环双向链表” ,其中包含三个要素:
排序链表: 节点应从小到大排序,因此应使用 中序遍历 “从小到大”访问树的节点。
双向链表: 在构建相邻节点的引用关系时,设前驱节点 pre 和当前节点 cur ,不仅应构建 pre.right = cur ,也应构建 cur.left = pre 。
循环链表: 设链表头节点 head 和尾节点 tail ,则应构建 head.left = tail 和 tail.right = head 。
作者:jyd
链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/solution/mian-shi-ti-36-er-cha-sou-suo-shu-yu-shuang-xian-5/
来源:力扣(LeetCode)
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
def dfs(cur):
if not cur: return
dfs(cur.left) # 递归左子树
if self.pre: # 修改节点引用
self.pre.right, cur.left = cur, self.pre
else: # 记录头节点
self.head = cur
self.pre = cur # 保存 cur
dfs(cur.right) # 递归右子树
if not root: return
self.pre = None
dfs(root)
self.head.left, self.pre.right = self.pre, self.head
return self.head
oldking (编辑过)2021-04-05
python3
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
if root == None: return None
p = root
stack = []
def fun(p):
if p == None:
return
fun(p.left)
stack.append(p)
fun(p.right)
fun(p)
n = len(stack)
for i in range(0,n):
stack[i].left = stack[i-1]
stack[i].right = stack[(i+1)%n]
return stack[0]
/*题目:给定数组,删除其中心元素
中心元素:奇数则1,偶则2个任意一个。
该值等于整个数组的平均值*/
class Solution {
public int findRepeatNumber(int[] nums int num) {
//1.对数组进行排序
nums = nums.sort();
// //2.1 遍历得到中心元素 or 计算得到这个均值
// int sum = 0, reverage;
// for (int i = 0; i < nums.length() - 1; i++) {
// sum += nums(i); //总和
// }
// reverage = sum/i; //均值
//2.找到均值下标
int order = 0;
if (num % 2 == 0) order = num/2; //为偶数的情况
if (num % 2 == 1) order = num/2; //为奇数的情况
//3. 循环将改元素后面的数据前移一位
for (int i = order; i < nums.length() - 1; i++) {
//前移
nums[i] = nums[i + 1];
}
// 去掉最后一位
nums[nums.length() - 1] = null;
return nums; //处理后的数组
}
}
肯定是跑不通的,在网上也没遇到相似的题目,主要还是自己连一种排序都不会默写,而且连面试官提示的思路都没有底气实现,这也是导致不通过的主要原因,还是基础的东西都没打好,不过本来就不是打算现在就上场的,不要气馁,等到7月份攒够了实力,再上就是了。
以上就是本题的内容和学习过程了,上一周因为参加了华为的机试,综测,专业面(挂了),所以也没有规律做题更新,专业面虽然选了自己本专业的自动化,但是面试官在问了我50min项目后,还是让我手撕了,当时脑子都不清楚,别说做题了,表现实在一般。
正好借这次经历鞭策一下自己,再接再厉,该走出舒适圈了。
周末把简历也升级了一下,考虑了更多的个人履历,项目,科研经历等等,实实在在的两页了。
欢迎讨论,共同进步。