文章目录
- 1.华为手撕代码总结
- 2.剑指offer
-
- 2.1 数字中重复的数字
- 2.1 二维数组中的查找
- 2.2 替换空格
- 2.3 从尾到头打印链表
- 2.4 重建二叉树
- 2.5用两个栈实现队列
- 2.6旋转数组的最小数
- 2.7斐波那契数列
- 2.8 跳台阶
- 2.8 变题:变态跳台阶
- 2.9 矩形覆盖
- 2.10二进制中1的个数
- 2.11数值的整数次方
- 2.12 打印从1到最大的n位数
- 2.13删除链表中的节点
- 2.14正则表达式匹配
- 2.15调整数组顺序使奇数位于偶数前面
- 2.13 链表中倒数第K个节点
- 2.14 反转链表
- 2.15 合并两个排序的链表
- 2.16 树的子结构
- 2.17 二叉树的镜像
- 2.18 顺时针打印矩阵
- 2.19 包含min函数的栈
- 2.20栈的压入弹出序列
- 2.21 从上往下打印二叉树
- 2.22 二叉搜索树的后序遍历结果
- 2.23 二叉树中和为某一值的路径
- 2.24 复杂链表的复制
- 2.25 二叉搜索树与双向链表
- 2.26 字符串的排序 (思路有些绕)
- 2.27 数组中出现次数超过一半的数字
- 2.28 最小的K个数
- 2.29 连续子数组的最大和
- 2.30 整数中1出现的次数
- 2.31 把数组排成最小的数
- 2.32 丑数
- 2.33 第一次只出现一次的字符串
- 2.34 数组中的逆序对
- 2.35 两个链表的公共节点
- 2.36 数字在排列数组中出现的次数
- 2.37 二叉树的深度
- 2.38 平衡二叉树
1.华为手撕代码总结
1.1排序问题
- 冒泡排序
def bubbleSort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n-i-1):
if arr[j] > arr[j+1] :
arr[j], arr[j+1] = arr[j+1], arr[j]
return arr
- 快排
思路:快速排序基本思想是:如序列[6,8,1,4,3,9],选择6作为基准数。从右向左扫描,寻找比基准数小的数字为3,交换6和3的位置,[3,8,1,4,6,9],接着从左向右扫描,寻找比基准数大的数字为8,交换6和8的位置,[3,6,1,4,8,9]。重复上述过程,直到基准数左边的数字都比其小,右边的数字都比其大。然后分别对基准数左边和右边的序列递归进行上述方法。详细可见:https://www.jianshu.com/p/2b2f1f79984e
def q_sort(L, left, right):
if left < right:
pivot = Partition(L, left, right)
q_sort(L, left, pivot - 1)
q_sort(L, pivot + 1, right)
return L
def Partition(L, left, right):
pivotkey = L[left]
while left < right:
while left < right and L[right] >= pivotkey:
right -= 1
L[left] = L[right]
while left < right and L[left] <= pivotkey:
left += 1
L[right] = L[left]
L[left] = pivotkey
return left
1.2链表求和
题目解析:
3->1->5->null
5->9->2->null
3+5=8
1+9=10,得到的进位1到下一个节点,第二个节点为0
1(上一个节点的进位)+5+2=8
结果为:
8->0->8->null
代码实现:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def addLists(self, l1, l2):
#判断是否某一链表为None,是返回另一条
if l1==None:return l2
if l2 == None:return l1
h1=l1
h2=l2
#只有两个链表的下一个节点数都为None,退出循环
while h1.next is not None or h2.next is not None:
#若只有一条链表的下一个节点为None,补充为0,不影响后续的加法结果
if h1.next ==None:h1.next=ListNode(0)
if h2.next ==None:h2.next=ListNode(0)
h1.val=h1.val+h2.val
#当加结果>=10,当前结果节点为个位数,下一个节点+1
if h1.val>=10:
h1.val=h1.val%10
h1.next.val+=1
h1=h1.next
h2=h2.next
else:
h1.val=h1.val+h2.val
#链表尾部的计算,如果>=10,则在尾部再添加一个节点
if h1.val>=10:
h1.val=h1.val%10
h1.next=ListNode(1)
return l1
1.3树的前中后序遍历(递归/循环写法)
- 递归
class Solution:
def inorderTraversal(self, root): #中序遍历
if not root:
return []
return self.inorderTraversal(root.left) + [root.val] + self.inorderTraversal(root.right)
def preorderTraversal(self, root): #前序遍历
if not root:
return []
return [root.val] + self.inorderTraversal(root.left) + self.inorderTraversal(root.right)
def postorderTraversal(self, root): #后序遍历
if not root:
return []
return self.inorderTraversal(root.left) + self.inorderTraversal(root.right) + [root.val]
- 循环实现
原理详细解释:https://www.cnblogs.com/bjwu/p/9284534.html
class Solution:
def inorderTraversal(self, root): #中序遍历
stack = [] #用栈实现
sol = [] #结果
curr = root #节点运动位置
while stack or curr:
if curr:
stack.append(curr)
curr = curr.left
else:
curr = stack.pop()
sol.append(curr.val)
curr = curr.right
return sol
def preorderTraversal(self, root): # 前序遍历
stack = []
sol = []
curr = root
while stack or curr:
if curr:
sol.append(curr.val)
stack.append(curr.right)
curr = curr.left
else:
curr = stack.pop()
return sol
def postorderTraversal(self, root): # 后序遍历
stack = []
sol = []
curr = root
while stack or curr:
if curr:
sol.append(curr.val)
stack.append(curr.left)
curr = curr.right
else:
curr = stack.pop()
return sol[::-1]
1.4树的链表化
<table>
<tr>
<td ><center><img src="https://img-blog.csdnimg.cn/20190511112024837.png" >输入 </center></td>
<td ><center><img src="https://img-blog.csdnimg.cn/20190511112042474.png" >输出</center></td>
</tr>
思路:对于每一颗子树进行后序遍历,将右子树连接到左子树的右子树上,将左子树连接到根节点的右子树上;递归进行遍历
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def flatten(self, root):
if root == None:
return None
self.flatten(root.left)
self.flatten(root.right)
if root.left != None:
p = root.left
while p.right != None:
p = p.right
p.right = root.right
root.right = root.left
root.left = None
1.5给一个初始饮料瓶数,三个空瓶换一瓶,可以赊一瓶,求最后能喝几瓶
def changeWater(cout_0):
# 喝水的瓶数
cout_1=0
if cout_0<2:
return 0
while cout_0>2:
cout_1+=cout_0//3
cout_0=cout_0//3+cout_0%3
if cout_0==2:
cout_1+=1
return cout_1
1.6岛屿最大面积问题
一个二维的01矩阵,上下左右都是1时算联通,求1组成岛的最大面积。
思路:递归思想,若发现某一位置的数为1,则它周围上下左右都要递归,但是!!!此处递归时需要注意的是,每找到一个位置的数为1时,就要把这个位置的数变为0,否则会进入死循环。
def max_area_of_island(grid):
if not grid:
return 0
l, h = len(grid), len(grid[0])
def dfs(i, j):
if 0 <= i < l and 0 <= j < h and grid[i][j]:
grid[i][j] = 0 #每找到一个位置的数为1时,就要把这个位置的数变为0
return 1 + dfs(i - 1, j) + dfs(i + 1, j) + dfs(i, j - 1) + dfs(i, j + 1)
return 0
#1)通俗写法
for i in range(lenr):
for j in range(lenc):
if grid[i][j] == 1:
count = dfs(i,j)
result = max(result,count)
return result
#2)精简写法
result = [dfs(i, j) for i in range(l) for j in range(h) if grid[i][j]]
return max(result) if result else 0
1.7自己面试手撕的5道算法题
看面经人家两轮技术面手撕两道算法题,到我这…手撕了5道…大概…也许…因为我不是科班出身???
一面(45min):
首先四道算法题,选一道15分钟写完,时间紧迫我选了第一道,给一个列表,求最大连续子序列和问题。
然后笔试题复盘,字符串反转问题改进版,("hello world"变成"world hello"的复杂版,只不过会有些字符干扰,需要判断删除。)
二面(1h):
给一个n数,返回列表,比如n = 13,输出值[1,10,11,12,13,2,3,4,5,6,7,8,9],0<n<50000;
链表反转;
给一个链表,遍历一次,找出倒数第k个节点(这个只说思路,不用手写代码了)
2.剑指offer
2.1 数字中重复的数字
思路1:建立一个同等大小的空数组,原数组的值为新数组的下标,访问一次置1,再次访问直接返回该值。
思路2:若当前值的hash值已经加过1了,则直接返回。
//思路1
int findRepeatNumber(int* nums, int numsSize){
int* arr = calloc(numsSize,sizeof(int)); //函数calloc()会将所分配的内存空间中的每一位都初始化为零
for (int i=0; i< numsSize; i++){
if (0 == arr[nums[i]]){
arr[nums[i]] = 1;
}
else{
return nums[i];
}
}
return -1;
}
//思路2:
int findRepeatNumber(int* nums, int numsSize){
int *hash = (int *)calloc(numsSize, sizeof(int));
for(int i = 0; i < numsSize; i++){
if(hash[nums[i]] == 1){
return nums[i];
} else {
hash[nums[i]]++;
}
}
return -1;
}
2.1 二维数组中的查找
def Find(target, array): # array 二维列表
if array == [[]]:
return False
m = len(array) # m行n列
n = len(array[0])
i = 0
j = n