python刷剑指offer(1-20)(一刷)
2019/07/28开始刷每天6题,一共66题,刷三遍,9月1号完成。
1、二维数组中的查找:
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
最开始的思路:
# -*- coding:utf-8 -*-
class Solution:
# array 二维列表,其实就是矩阵
def Find(self, target, array):
# write code here
# 矩阵的行
rows = len(array)
# 矩阵的列
cols = len(array[0])
# 遍历矩阵的每一个元素
for i in range(rows):
for j in range(cols):
# 判断矩阵中是否含有该整数
if target == array[i][j]:
print("找到啦")
return True
return False
这样写更好:
class Solution:
# array 二维列表,其实就是矩阵
def Find(self, target, array):
# write code here
# 矩阵的行
rows = len(array) - 1
# 矩阵的列
cols = len(array[0]) - 1
# 矩阵是有序的
i = rows # 最后一行
j = 0 # 第一列
while j <= cols and i >= 0:
# 如果该整数小于x
if target < array[i][j]:
# 行减小
i -= 1
# 如果该整数小于x
elif target > array[i][j]:
# 列增加
j += 1
# 正好相等,找到了
else:
return True
# 没找到
return False
2、请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
# -*- coding:utf-8 -*-
class Solution:
# s 源字符串
def replaceSpace(self, s):
# write code here
return s.replace(" ", "%20")
不用内置的函数:
def replaceSpace(s):
# write code here
# 不用内置的函数
# 创建一个新的空字符串
new_str = ""
# 遍历源字符串
for ele in s:
# print(s)
# 判断遍历出的字符i是否为空格
# 不为空格
if ele.strip():
new_str += ele
# 空格
else:
new_str += "%20"
return new_str
3、输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
解法一:
class Solution:
# 返回从尾部到头部的列表值序列,例如[1,2,3]
def printListFromTailToHead(self, listNode):
# write code here
# 注意这是链表 取下一个:listNode.next 取值:listNode.val
new_list = []
# 只要链表非空
while listNode:
# 在新的序列,每次都是0位置插入值
new_list.insert(0, listNode.val)
listNode = listNode.next
return new_list
解法二:
class Solution:
# 返回从尾部到头部的列表值序列,例如[1,2,3]
def printListFromTailToHead(self, listNode):
# write code here
# 注意这是链表 取下一个:listNode.next 取值:listNode.val
new_list = []
# 只要链表非空
while listNode:
# 新的序列尾部追加值
new_list.append(listNode.val)
listNode = listNode.next
# 最后进行逆序
return new_list[::-1]
4、输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
代码:
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回构造的TreeNode根节点
def reConstructBinaryTree(self, pre, tin):
# write code here
# 判断是否为空
if not pre or not tin:
return
# 不为空
# 1、找到根节点,在前序遍历的首元素
root = TreeNode(pre[0])
# 2、找到根节点在中序遍历序列的位置
index = tin.index(root.val)
# 3、利用递归重建二叉树
# 3.1、中序遍历中,根节点左边的是左子树,右边的是右子树
# 3.2、前序遍历中,也可以安装根节点在中序遍历的位置,将前序遍历分为左子树和右子树。
root.left = self.reConstructBinaryTree(pre[1:index+1], tin[:index]) # 前序[去除根节点:左子树],中序[左子树:根节点前一个元素]
root.right = self.reConstructBinaryTree(pre[index+1:], tin[index+1:]) # 前序[右子树],中序[根节点后一个元素:右子树]
return root
解题思路:采用递归的思想,前序遍历的第一个数字就是根节点,然后扫描中序遍历,确定中序遍历中根结点的位置,根节点位置之前的就是左子树的中序遍历,根节点后面的就是右子树的中序遍历。按照中序遍历根节点的位置,也可以把前序遍历分为左子树的前序遍历和右子树的前序遍历。
5、用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
# 初始化两个栈
self.stack1 = []
self.stack2 = [] def push(self, node):
# write code here
# 压栈的操作
self.stack1.append(node) def pop(self):
# return xx
# 弹栈的操作
# 如果尚未在栈(该队列)中添加任何元素,则直接返回空
# if self.stack1 == []:
# print("请先在队列中添加元素")
# return None
# 其实一个栈就可以实现了
# self.stack1.pop(0)
if self.stack2 == []:
# 一直弹栈,直至队列中元素为空 !!!!!!!!!!!!
while self.stack1:
# 栈1中弹出
a = self.stack1.pop()
# 栈2中压入
self.stack2.append(a)
return self.stack2.pop()
6、把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
第一种方法:直接在数组中利用 自带的查找函数找到最小的那个,当然,这样面试官可能直接就让你滚粗了。
第二种方法:稍微优化一下,由题目可知,整个数组可以分为两个子数组,前面的子数组的最后一个元素肯定大于或者等于后面子数组的都一个元素,那么找到第一个前面数字大于或者等于后面数字的情况,那么后面这个较小的数字就是最小值
以上两种方法的时间复杂度均为O(N),在真实面试中肯定不行。
下面介绍面试官想要你给出的解法,即利用二分法进行查找。
以数组a[3,4,5,1,2]为例。
1.设置两个指针low,high,分别指向第一个以及最后一个元素 。
2.设置中间指针mid,指向中间元素,mid=low+(high-low)/2。
3.这里有三种情况:
(1)a[mid]>a[high],此时最小值一定在中间值的右边,设置low=mid+1。
(2)a[mid]>a[low],此时最小值一定在中间值的左边,设置high=mid。
(3) a[mid]=a[high],此时无法判断最小在左边还是右边,只有一个一个判断,即high=high-1。
最后返回a[low]的值。
# -*- coding:utf-8 -*-
class Solution:
def minNumberInRotateArray(self, rotateArray):
# write code here
# pre = -7e20
pre = -float("inf")
for num in rotateArray:
if num < pre :
return num
pre = num if len(rotateArray) == 0:
return 0
return rotateArray[0]
7、大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
n<=39
# -*- coding:utf-8 -*-
class Solution:
def Fibonacci(self, n):
# write code here
assert n <= 39, "n <= 39" # 斐波那契数列
f_list = [0]
# 循环n次
a = 0
b = 1
for i in range(n):
a, b = b, a + b
f_list.append(a) # 输出数列的第n项
return f_list[n]
8、一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
比较倾向于找规律的解法,f(1) = 1, f(2) = 2, f(3) = 3, f(4) = 5, 可以总结出f(n) = f(n-1) + f(n-2)的规律,但是为什么会出现这样的规律呢?
假设现在6个台阶,我们可以从第5跳一步到6,这样的话有多少种方案跳到5就有多少种方案跳到6;
另外我们也可以从4一次跳两步跳到6,跳到4有多少种方案的话,就有多少种方案跳到6(注意不要多算了),
其他的不能从3跳到6什么的啦,所以最后就是f(6) = f(5) + f(4)。
这样子也很好理解变态跳台阶的问题了。
# -*- coding:utf-8 -*-
class Solution:
def jumpFloor(self, number):
# write code here
# 通过分析,知道本质是斐波那契数列问题
# 构造数列
# f_list = []
a = 1
b = 1
for i in range(number):
a, b = b, a+b
# f_list.append(a) return a
9、变态跳台阶:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
# -*- coding:utf-8 -*-
import math
class Solution:
def jumpFloorII(self, number):
# write code here
if number <= 0:
return 0
return math.pow(2, number-1)
10、我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
这道题的思路和青蛙跳台阶是一样的
# -*- coding:utf-8 -*-
class Solution:
def rectCover(self, number):
# write code here
if number == 0:
return 0
a = 1
b = 1
for i in range(number):
a, b = b, a+b
return a
11、输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
# -*- coding:utf-8 -*-
class Solution:
def NumberOf1(self, n):
# write code here
count = 0
for i in range(32):
count += (n >> i)&1
return count
12、给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
# -*- coding:utf-8 -*-
class Solution:
def Power(self, base, exponent):
# write code here
# 要考虑多种情况
flag = 1
# 初始化输出的结果
result = 1
# 1、exponent为负数
if exponent < 0:
flag = -1
# 2、exponent为0
if exponent == 0:
return 1
# 正常情况 exponent取绝对值
for i in range(abs(exponent)):
result *= base
if flag == -1:
result = 1 / result
return result
13、输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
解法一:新建数组
解法二:类似冒泡排序
/**
* 1.要想保证原有次序,则只能顺次移动或相邻交换。
* 2.i从左向右遍历,找到第一个偶数。
* 3.j从i+1开始向后找,直到找到第一个奇数。
* 4.将[i,...,j-1]的元素整体后移一位,最后将找到的奇数放入i位置,然后i++。
* 5.終止條件:j向後遍歷查找失敗。
*/
# -*- coding:utf-8 -*-
class Solution:
def reOrderArray(self, array):
# write code here
# 找两个数组
array1 = []
array2 = []
# 遍历原数组
for ele in array:
if ele % 2 == 1:
array1.append(ele)
elif ele % 2 == 0:
array2.append(ele)
return array1 + array2
14、输入一个链表,输出该链表中倒数第k个结点。
# 输入一个链表,输出该链表中倒数第k个结点。 # -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None class Solution:
def FindKthToTail(self, head, k):
# write code here
# 思路:
# 1、用两个指针a和b同时指向头节点
# 2、指针a先走k-1步,到达了第k个节点,指针b不动
# 3、此时指针a和b同时移动,指针a走到尾节点终止,此时指针b所在位置即倒数第k个节点 # 特殊情况
# if not head or k <= 0:
if head is None or k <= 0:
return cursor_a = head
cursor_b = head for i in range(k-1):
# 注意:这里要考虑k可能大于链表长度的情况
if cursor_a.next != None:
cursor_a = cursor_a.next
else:
return while cursor_a.next != None:
cursor_a = cursor_a.next
cursor_b = cursor_b.next return cursor_b
解法二:将链表转换成列表
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None class Solution:
def FindKthToTail(self, head, k):
# write code here
l=[]
while head!=None:
l.append(head)
head=head.next
if k>len(l) or k<1:
return
return l[-k]
15、输入一个链表,反转链表后,输出新链表的表头。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
# write code here
'''
先将当前节点数对应的下一个节点数保存下来tmp = pHead.next,
然后将上个节点数last赋值给pHead.next(初始last为None)。
当前节点pHead赋值给last(成为上一个节点),
最后将下一个节点tmp赋值给pHead(成为当前结点)。
'''
if pHead is None or pHead.next is None:
return pHead
last = None
while pHead:
# 暂存下一个节点,避免节点丢失
tmp = pHead.next
# 链表反转,下一个节点指向上一个节点
pHead.next = last
# 当前节点赋值给last
last = pHead
# 最后将下一个节点赋值给pHead
pHead = tmp
return last
16、输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
# write code here
# 新建一个链表(随便填一个数进去,最后返回的时候返回首节点.next即可),用于保存合并后的链表
new_p = ListNode(666)
# 保存这个新链表
p = new_p # 遍历输入的两个链表
while pHead1 and pHead2:
if pHead1.val <= pHead2.val:
# 新链表节点指向该节点
new_p.next = pHead1
# 该链表要向后移动一个
pHead1 = pHead1.next
elif pHead1.val > pHead2.val:
# 新链表节点指向该节点
new_p.next = pHead2
# 该链表要向后移动一个
pHead2 = pHead2.next
# 每添加一个节点,新链表向后移动一个节点
new_p = new_p.next
# 上诉遍历很可能会出现其中一个链表没有遍历完的情况
# 比如极端情况:链表1:[1] 链表2:[2, 3, 4],则链表2根本不会遍历
# while None and 1: 则下面的代码不会执行,即一个链表遍历完了,循环就会结束
# if pHead1:
# new_p.next = pHead1
# elif pHead2:
# new_p.next = pHead2 # 或者一行代码搞定
new_p.next = pHead1 or pHead2 # 注意返回的是节点的next
return p.next
17、输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
思路:
对于两棵二叉树来说,要判断B是不是A的子结构,首先第一步在树A中查找与B根节点的值一样的节点。
通常对于查找树中某一个节点,我们都是采用递归的方法来遍历整棵树。
第二步就是判断树A中以R为根节点的子树是不是和树B具有相同的结构。
这里同样利用到了递归的方法,如果节点R的值和树的根节点不相同,则以R为根节点的子树和树B肯定不具有相同的节点;
如果它们值是相同的,则递归的判断各自的左右节点的值是不是相同。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def HasSubtree(self, pRoot1, pRoot2):
# write code here
'''
首先第一步在树A中查找与B根节点的值一样的节点。 通常对于查找树中某一个节点,我们都是采用递归的方法来遍历整棵树。 第二步就是判断树A中以R为根节点的子树是不是和树B具有相同的结构。 这里同样利用到了递归的方法,如果节点R的值和树的根节点不相同,则以R为根节点的子树和树B肯定不具有相同的节点; 如果它们值是相同的,则递归的判断各自的左右节点的值是不是相同。 递归的终止条件是我们达到了树A或者树B的叶节点。
'''
result = False
if pRoot1 != None and pRoot2 != None:
# 1、在树1中查找与数2根节点的值一样的节点
if pRoot1.val == pRoot2.val:
# 2.1、判断树1中以R为根节点的子树是不是和树2具有相同的结构。
result = self.is_subtree(pRoot1, pRoot2)
# 2.2、到这里说明树1的根节点不是数2的根节点,找树1左子树的节点
if not result:
result = self.HasSubtree(pRoot1.left, pRoot2)
# 2.3、同理判断树2的右子树
if not result:
result = self.HasSubtree(pRoot1.right, pRoot2)
return result # 用于递归判断树的每个节点是否相同
# 需要注意的地方是: 前两个if语句不可以颠倒顺序
# 如果颠倒顺序, 会先判断pRoot1是否为None, 其实这个时候pRoot2的结点已经遍历完成确定相等了, 但是返回了False, 判断错误 def is_subtree(self, pRoot1, pRoot2):
if pRoot2 == None:
return True if pRoot1 == None:
return False if pRoot1.val != pRoot2.val:
return False # 判断左右节点
return self.is_subtree(pRoot1.left, pRoot2.left) and self.is_subtree(pRoot1.right, pRoot2.right)
18、操作给定的二叉树,将其变换为源二叉树的镜像。
二叉树的镜像定义:源二叉树
8
/ \
6 10
/ \ / \
5 7 9 11
镜像二叉树
8
/ \
10 6
/ \ / \
11 9 7 5
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回镜像树的根节点
def Mirror(self, root):
# write code here
if root != None:
# 交换左右节点
root.left, root.right = root.right, root.left
# 将交换后的左右节点,依次加入镜像树中
self.Mirror(root.left)
self.Mirror(root.right)
19、输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10。
思路:
每次打印并删除矩阵的第一行,然后将矩阵逆时针翻转90度,直至打印出全部结果
# -*- coding:utf-8 -*-
class Solution:
# matrix类型为二维列表,需要返回列表
def printMatrix(self, matrix):
# write code here
res = []
while matrix:
res += matrix.pop(0)
# print(matrix)
# 如果matrix为空,就不要翻转了,否则会报错(超出索引)
if matrix:
matrix = self.rotate_matrix(matrix)
return res def rotate_matrix(self, matrix):
'''逆时针方向旋转90°矩阵'''
# 新矩阵
new_matrix = []
row = len(matrix)
col = len(matrix[0])
# 行列互换,每次先遍历列方向,这样可以按照列的方向读取矩阵元素
for i in range(col):
new_line = []
# print(" ")
for j in range(row):
# print(matrix[j][col -1 -i])
# [col-1-i] 在这里是固定的,比如第一次循环,就是倒数第一个 -1,下一次则是-2
new_line.append(matrix[j][col -1 -i])
new_matrix.append(new_line)
return new_matrix m = [
[1,2,3],
[4,5,6],
[7,8,9]]
s = Solution() # s.rotate_matrix(m)
s.printMatrix(m)
20、定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.stack = []
# 创建一个可以瞬间返回最小值的栈,保证这个辅助栈的栈顶元素一直是最小的,取栈顶元素[-1]
self.min_stack = [] def push(self, node):
# write code here
self.stack.append(node)
# 如果最小值栈没有元素,或,添加的这个node比最小值栈的元素小,则加入最小值栈
if self.min_stack == [] or node < self.min_stack[-1]:
self.min_stack.append(node) def pop(self):
# write code here
# 如果弹出的元素,主栈和辅助栈相同,则都要弹出
if self.stack[-1] == self.min_stack[-1]:
self.min_stack.pop()
self.stack.pop() def top(self):
# write code here
return self.stack[-1] def min(self):
# write code here
return self.min_stack[-1]
python刷剑指offer(1-20)(一刷)的更多相关文章
- 剑指offer(20)包含min函数的栈
题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数. 题目分析 首先一开始我们分析得到最小值肯定要比较嘛,和栈里面的数据一一比较,但是栈这种数据结构,你又只能和栈顶弹出来的 ...
- 剑指offer计划20( 搜索与回溯算法中等)---java
1.1.题目1 剑指 Offer 07. 重建二叉树 1.2.解法 注释解法. 1.3.代码 class Solution { int[] preorder; HashMap<Integer, ...
- python刷剑指offer(21-40)(一刷)
21.输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序 ...
- 剑指offer 面试20题
面试20题: 题目:表示数值的字符串 题:请实现一个函数用来判断字符串是否表示数值(包括整数和小数).例如,字符串"+100","5e2","-123 ...
- (python)剑指Offer(第二版)面试题14:剪绳子
题目 给你一根长度为n的绳子,请把绳子剪成m段 (m和n都是整数,n>1并且m>1)每段绳子的长度记为k[0],k[1],…,k[m].请问k[0]k[1]…*k[m]可能的最大乘积是多少 ...
- (python)剑指Offer 面试题51:数组中重复的数字
问题描述 在长度为n的数组中,所有的元素都是0到n-1的范围内. 数组中的某些数字是重复的,但不知道有几个重复的数字,也不知道重复了几次,请找出任意重复的数字. 例如,输入长度为7的数组{2,3,1, ...
- (python)剑指Offer:数组中重复的数字
问题描述 在长度为n的数组中,所有的元素都是0到n-1的范围内. 数组中的某些数字是重复的,但不知道有几个重复的数字,也不知道重复了几次,请找出任意重复的数字. 例如,输入长度为7的数组{2,3,1, ...
- python实现剑指offer删除链表中重复的节点
题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后 ...
- 用js刷剑指offer(丑数)
题目描述 把只包含质因子2.3和5的数称作丑数(Ugly Number).例如6.8都是丑数,但14不是,因为它包含质因子7. 习惯上我们把1当做是第一个丑数.求按从小到大的顺序的第N个丑数. 思路 ...
随机推荐
- CKKS Part5: CKKS的重缩放
本文翻译于 CKKS EXPLAINED, PART 5: RESCALING,主要介绍CKKS方案中最重要的技术- rescaling,重缩放技术 介绍 在CKKS的前一篇文章 CKKS Part4 ...
- ApacheCN 计算机视觉译文集 20211110 更新
OpenCV3 和 Qt5 计算机视觉 零.前言 一.OpenCV 和 Qt 简介 二.创建我们的第一个 Qt 和 OpenCV 项目 三.创建一个全面的 Qt + OpenCV 项目 四.Mat和Q ...
- Halcon视觉入门芯片识别
Halcon视觉入门芯片识别 需求 有如下图的一个摆盘,摆盘的方格中摆放芯片,一个格子中只放一个,我们需要知道每个方格中是否有芯片去指导我们将芯片放到空的方格中. 分析 通过图片分析得出 我们感兴趣的 ...
- 有关OPenCV的几个库函数的使用
转载请注明来源:https://www.cnblogs.com/hookjc/ 1) IplImage* cvCreateImage( CvSize size, int depth, int chan ...
- Spring中声明式事务处理和编程式事务处理的区别
编程式事务:所谓编程式事务指的是通过编码方式实现事务,即类似于JDBC编程实现事务管理.管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManag ...
- Java 给Word每一页设置不同文字水印效果
Word中设置水印时,可预设的文字或自定义文字设置为水印效果,但通常添加水印效果时,会对所有页面都设置成统一效果,如果需要对每一页或者某个页面设置不同的水印效果,则可以参考本文中的方法.下面,将以Ja ...
- HTTP协议和HTTPS协议的那些事
文章目录 HTTPS VS HTTP HTTPS=HTTP+加密+证书+完整性保护 加密 对称加密 非对称加密 混合加密 证书 完整性保护 HTTPS并不能取代HTTP SSL是把双刃剑 HTTPS的 ...
- service与systemctl命令比较
本文将比较 linux 的 service 和 systemctl 命令,先分别简单介绍这两个命令的基础用法,然后进行比较. 从 CentOS 7.x 开始,CentOS 开始使用 systemd 服 ...
- 数据库delete from和truncate删除的区别详解
一:区别 1.delete from 后面可以直接接条件,truncate不可以 2.delete from 记录是一条条删除的,所删除的每行记录都会进入日志,而truncate一次性删除整个页,因此 ...
- [自动化]ansible-系统安全加固整改
基线漏洞安全整改 修复环境:centos7及以上 安全基线的概念 安全基线是一个信息系统的最小安全保证,即该信息系统最基本需要满足的安全要求.信息 系统安全往往需要在安全付出成本与所能够承受的安全风险 ...