-
Notifications
You must be signed in to change notification settings - Fork 0
/
content.json
1 lines (1 loc) · 82 KB
/
content.json
1
[{"title":"有关ubuntu的琐碎小事儿","date":"2020-06-22T08:19:22.231Z","path":"2020/06/22/有关ubuntu的琐碎小事儿 - 副本/","text":"1.安装电子书阅读器: 1sudo apt install fbreader 2.安装谷歌访问助手 a.百度下载谷歌访问助手 .crx **文件,将其重命名为.zip文件,然后解压; b.打开,将其中_metadata文件重命名为metadata**; c.chrome浏览器打开拓展程序界面开发者模式,加载已解压文件夹,done.3.Ubuntu中python版本切换 a.ubuntu中将python3设置为默认,执行: 12sudo update-alternatives --install /usr/bin/python python /usr/bin/python2 100sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 150 b.ubuntu中将python2设置为默认,执行: 1sudo update-alternatives --config python","tags":[{"name":"Ubuntu","slug":"Ubuntu","permalink":"http://yoursite.com/tags/Ubuntu/"}]},{"title":"面试题9:用两个栈实现队列","date":"2020-01-09T13:51:38.418Z","path":"2020/01/09/面试题9:用两个栈实现队列/","text":"题目:https://www.nowcoder.com/ta/coding-interviews 用两个栈来实现一个队列;完成队列的Push和Pop操作; 思考: 栈是有序的 LIFO,也就是后进先出(先进后出);队列是有序的FIFO,也就是先进先出。 也就是要用两个先进后出的栈,实现先进先出的队列。 例如:stack1={a}; stack2={}; 压入b,c:stack1={c,b,a}(a在栈底,c在栈顶);stack2={}; 当我们想要弹出a时,由于a在stack1底,不能直接弹出,于是我们先将stack1的元素按照栈先入后出的原则弹出并压入stack2有:stack2={a,b,c}(此时,a在栈顶,c在栈底); 于是,可以顺利从stack2中弹出a,总体上实现队列先入先出的性质。 总结: push()方法可以利用list.append()方法实现; pop()方法:判断stack2是否为空,不空,依次弹出栈顶元素;为空,则先将stack1中元素按照先入后出的原则弹出并压入stack2,然后弹出stack2中栈顶元素;总体实现队列功能。 python中可用列表表示后入先出的栈,list.pop()默认删除列表最后一个元素(此外,pop()有可选参数,如:list1.pop(1),1为待删除元素的索引,pop方法返回删除的列表元素); push()方法,可看作用list.append()往列表尾追加新元素。 1234list1 = ['Google', 'Runoob', 'Taobao']list_pop=list1.pop()print( \"删除的项为 :\", list_pop)print( \"列表现在为 : \", list1) 删除的项为 : Taobao 列表现在为 : ['Google', 'Runoob']123list2 = ['1', '2', '3']list_push=list2.append('new_4')print( \"列表现在为 : \", list2) 列表现在为 : ['1', '2', '3', 'new_4']123456789101112131415161718192021222324252627class Solution: def __init__(self): self.stack1=[] self.stack2=['x','y']#顺序,先x,再y,说明在之前有:stack1={'y','x'},y比x先入栈 # def push(self, node):# self.stack1.append(node)#直接在stack1中压入元素#这是一个参考博主的写法,增加了对stack1是否为空的判断及操作 def push(self, node): if self.stack1:#如果stack1非空,在其中压入元素 self.stack1.append(node) else:#若stack1空 while self.stack2:#在stack2非空时(此时,说明其中数据先进入队列) self.stack1.append(self.stack2.pop())#先将stack2中元素弹出并压入到stack1,形成新的待追加新元素的栈,#我猜这样是为了方便后面的pop处理,因为这样不用判断stack2是否为空(经过形成新的stack1的处理,stack2始终为空),直接将stack1元素弹出压入stack2,再进行pop就好 self.stack1.append(node)#然后压入新的元素,此步不可少,不然会造成新压入的第一个元素缺失 def pop(self): if self.stack2: return self.stack2.pop() elif self.stack1: while self.stack1: self.stack2.append(self.stack1.pop()) return self.stack2.pop() else: return None 123456method = Solution()for i in range(1,6): push = method.push(i)print(\"stack1=\",method.stack1)print(\"stack2=\",method.stack2) stack1= ['y', 'x', 1, 2, 3, 4, 5] stack2= []1234pop = method.pop()print(\"stack1=\",method.stack1)print(\"弹出的元素为\",pop)print(\"stack2=\",method.stack2) stack1= [] 弹出的元素为 y stack2= [5, 4, 3, 2, 1, 'x']由于在push方法中增加了对stack2的处理,原pop方法可以简化,因为处理后的stack2始终为空 1234567891011121314class Solution1: def __init__(self): self.stack1=[] self.stack2=[6,7] def push(self, node): if self.stack2: while self.stack2: self.stack1.append(self.stack2.pop()) self.stack1.append(node) def pop(self): if self.stack1:#如果stack1不空 while self.stack1: self.stack2.append(self.stack1.pop())#直接将stack1中元素弹出,再压入stack2,形成待弹出栈 return self.stack2.pop() 123456method = Solution1()for i in range(1,6): push = method.push(i)print(\"stack1=\",method.stack1)print(\"stack2=\",method.stack2) stack1= [7, 6, 1, 2, 3, 4, 5] stack2= []1234pop = method.pop()print(\"stack1=\",method.stack1)print(\"弹出的元素为\",pop)print(\"stack2=\",method.stack2) stack1= [] 弹出的元素为 7 stack2= [5, 4, 3, 2, 1, 6]reference: 1.https://blog.csdn.net/Datawhale/article/details/82118919 2.https://blog.csdn.net/fuxuemingzhu/article/details/79499461 12","tags":[{"name":"剑指offer","slug":"剑指offer","permalink":"http://yoursite.com/tags/%E5%89%91%E6%8C%87offer/"},{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"面试题6:从头到尾打印链表","date":"2020-01-09T13:51:38.403Z","path":"2020/01/09/面试题6:从尾到头打印链表/","text":"题目:https://www.nowcoder.com/ta/coding-interviews 输入一个链表: 按链表值从尾到头的顺序返回一个ArrayList。 定义链表: 1234class ListNode: def __init__(self, x, next=None): self.val = x self.next = next 思考: 读取链表中的元素,放入列表,倒序输出 12345678class Solution: def printListFromTailToHead(self, listNode): list=[] while listNode: list.append(listNode.val) listNode = listNode.next# return list[::1]#顺序列表 return list[::-1]#逆序列表 疑问:链表的顺序感觉上跟直觉相反?在这里,用循环创建链表结构,最先创建的是末节点. 1234567# 根据节点定义,用循环创建一个链表结构:# 5,4,3,2,1head = None#最后一个指向Nonefor i in range(1, 6): head = ListNode(i,head) print(\"这是生成的链表数据\",head.val) 这是生成的链表数据 1 这是生成的链表数据 2 这是生成的链表数据 3 这是生成的链表数据 4 这是生成的链表数据 51234method = Solution()answer = method.printListFromTailToHead(head)answer [1, 2, 3, 4, 5]python列表切片 1234567891011121314151617181920# -*- coding: UTF-8 -*-s = 'abcdefg'# 返回从起始位置到索引位置 2 处的字符串切片print(s[:3]) # 输出 'abc'# 返回从第三个索引位置到结尾的字符串切片print(s[3:]) # 输出 'defg'# 字符串逆序输出print(s[::-1]) # 输出 'gfedcba'# 输出从开始位置间隔一个字符组成的字符串print(s[::2]) # 输出 'aceg'print(range(10)[::2]) # 会直接输出range(0, 10, 2)print(list(range(10)[::2])) #这样才能输出偶数:[0, 2, 4, 6, 8]# 它们也可以相互结合使用。# 从索引位置 6 到索引位置 2,逆向间隔一个字符print(s[6:2:-2]) # 输出'ge' abc defg gfedcba aceg range(0, 10, 2) ge1print(range(10)[::2]) range(0, 10, 2)reference: 1.https://blog.csdn.net/Datawhale/article/details/81947290 12","tags":[{"name":"剑指offer","slug":"剑指offer","permalink":"http://yoursite.com/tags/%E5%89%91%E6%8C%87offer/"},{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"面试题7:重建二叉树","date":"2020-01-09T13:51:38.403Z","path":"2020/01/09/面试题7:重建二叉树/","text":"题目: https://www.nowcoder.com/ta/coding-interviews 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。 思考: 前序遍历的第一个值是二叉树的根节点,中旬遍历中根节点(索引为i)前边的都是左子树的值(对应前序遍历[1:i+1]中的元素),后边的是右子树的值(对应前序遍历[i+1:]中的元素); 递归重复以上过程:取前序遍历[1:i+1]和中序遍历[:i]中的值重复上一个过程得到左子树,取前序遍历[i+1:]和中序遍历[i+1:]得到右子树 12345678910111213141516171819202122#定义树节点class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None def PrintFromTopToBottom(root):#打印二叉树(从上往下,同层节点从左至右打印) array = [] result = [] if root == None: return result array.append(root) while array: newNode = array.pop(0) result.append(newNode.val) if newNode.left != None: array.append(newNode.left) if newNode.right != None: array.append(newNode.right) return result 方法1 123456789101112131415161718class Solution: def reConstructBinaryTree(self, preorder,inorder): if len(preorder) == 0: return None if len(preorder) == 1: return TreeNode(preorder[0]) else: index = inorder.index(preorder[0])#得到根节点在中序遍历中的索引 node = TreeNode(preorder[0])#根节点 preorderLeft = preorder[1:index+1]#左子树的元素 inorderLeft = inorder[:index] preorderRight = preorder[index+1:]#右子树的元素 inorderRight = inorder[index+1:] node.left = self.reConstructBinaryTree(preorderLeft,inorderLeft)#递归调用重建方法self.XX() node.right = self.reConstructBinaryTree(preorderRight,inorderRight) return node 1234567solution = Solution()preorder_seq = [1, 2, 4, 7, 3, 5, 6, 8]middleorder_seq = [4, 7, 2, 1, 5, 3, 8, 6]# print(middleorder_seq[-4:])treeRoot1 = solution.reConstructBinaryTree(preorder_seq, middleorder_seq)newArray = PrintFromTopToBottom(treeRoot1)print(newArray) [5, 3, 8, 6] [1, 2, 3, 4, 5, 6, 7, 8]方法2 123456789101112131415class Solution: def construct_tree(self, preorder=None, inorder=None): \"\"\" 构建二叉树 \"\"\" if not preorder or not inorder: return None index = inorder.index(preorder[0]) left = inorder[0:index] right = inorder[index+1:] root = TreeNode(preorder[0]) root.left = construct_tree(preorder[1:1+len(left)], left)#这里其实有len(left)=index root.right = construct_tree(preorder[-len(right):], right) #preorder[-3:]表示从-3到末尾处,包含-3这个索引(倒数第三)位置的元素 return root [1, 2, 3, 4, 5, 6, 7, 8]参考: https://blog.csdn.net/Datawhale/article/details/81948283 https://blog.csdn.net/fuxuemingzhu/article/details/70303139 https://blog.csdn.net/u010005281/article/details/79493413 12 12 12 12 12 12 12 12 12","tags":[{"name":"剑指offer","slug":"剑指offer","permalink":"http://yoursite.com/tags/%E5%89%91%E6%8C%87offer/"},{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"面试题32:分行从上到下打印二叉树","date":"2020-01-09T13:51:38.387Z","path":"2020/01/09/面试题32:分行从上到下打印二叉树/","text":"题目:https://www.nowcoder.com/ta/coding-interviews?query=&asc=true&order=&page=3 从上到下按层打印二叉树,与之前不同的是:同一层节点从左至右顺序打印(输出),每一层打印(输出)一行。 理解: 这里,根据要求返回二维列表,容易知道,为了把二叉树的每一行单独打印到一行,用列表存储每一层的节点值:[ [ ], [ ], [ ], …, [ ] ],第几层对应第几个子序列。 12345class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None 12345678910111213141516171819202122class Solution1:# 返回二维列表[[1,2],[4,5]] def Print(self,pRoot): result = [] self.level(pRoot, 0, result) return result def level(self, root, level, result): if not root: return None if level == len(result): result.append([])#为每一层建立子序列, #实际上这里需要追加子序列的情况:1.根节点时level=0=len(result),建立子序列; #2.假如左节点成立的话,左节点时level+1=len(result),需要建立子序列。而此后在判断同层右节点时,level已经变化多次,不再需要建立子序列。 #3.假如左节点不成立的话,在判断右节点时level+1=len(result),需要建立子序列。 result[level].append(root.val)#将节点值放入对应的子序列 if root.left: self.level(root.left, level+1, result)#左节点 if root.right: self.level(root.right, level+1, result) 12345678910111213141516171819root = TreeNode(8)a = TreeNode(6)b = TreeNode(10)c = TreeNode(5)d = TreeNode(7)e = TreeNode(9)f = TreeNode(11)g = TreeNode(12)h = TreeNode(13) root.left = aroot.right = ba.left = ca.right = db.left = eb.right = fd.left = gd.right = h 123method = Solution1()answer = method.Print(root)answer [[8], [6, 10], [5, 7, 9, 11], [12, 13]]参考: 1.https://blog.csdn.net/fuxuemingzhu/article/details/79725053 2.https://blog.csdn.net/qq_18254385/article/details/94736589","tags":[{"name":"剑指offer","slug":"剑指offer","permalink":"http://yoursite.com/tags/%E5%89%91%E6%8C%87offer/"},{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"面试题4:二维数组中的查找","date":"2020-01-09T13:51:38.387Z","path":"2020/01/09/面试题4:二维数组中的查找/","text":"题目:在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序;每一列都按照从上到下递增的顺序排序;请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 思考:什么是二维数组?直观的想到矩阵,实际上python当中没有数组的概念, 而是列表(List), 二维列表相当于二维数组 。如下: 1234import numpy as nparray = np.array([[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]])array# array([[ 1, 2, 8, 9], [ 2, 4, 9, 12], [ 4, 7, 10, 13], [ 6, 8, 11, 15]])实现 1.最直观的是直接循环遍历每一个元素,判断是否等于给定的整数,如果相等则输出存在,否则不存在 123456789101112class Solution: # array 二维列表 def Find(self, target, array): for i in range(len(array)):# row = len(array) #列表的长度(有多少个元素,这里元素也是列表),可以看作是二维数组的行数 for j in range(len(array[0])):#col = len(array[0])#列表第0个元素的长度,可以看作是二维数组的列数 if array[i][j] == target: return True return Falsemethod = Solution()answer = method.Find(70,array)answer 2.由于数组元素是分别按行按列递增的,考虑:将目标值与较大的元素进行比较,通过排除较大值向下遍历 从最后一行第一列开始遍历,记给定的整数为target,数组元素为array[i][j]如果 target < array[i][j] 则行数减1如果 target > array[i][j] 则列数加1如果 target == array[i][j] 则返还True 123456789101112131415161718class Solution: # array 二维列表 def Find(self, target, array): fond = 0 row = len(array) - 1 col = len(array[0]) - 1 i = row j = 0 while i >= 0 and j <= col: if target < array[i][j]: i = i - 1 elif target > array[i][j]: j = j + 1 else: return True else: return False 123method = Solution()answer=method.Find(5,array)answer","tags":[{"name":"剑指offer","slug":"剑指offer","permalink":"http://yoursite.com/tags/%E5%89%91%E6%8C%87offer/"},{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"面试题5:空格替换","date":"2020-01-09T13:51:38.387Z","path":"2020/01/09/面试题5:空格替换/","text":"题目:https://www.nowcoder.com/ta/coding-interviews 将特殊字符替换成ASCII码,例如空格对应32(0x20).在网络编程的背景中为了使服务器识别特殊字符需要做的转换是: 空格—>’%20’。 例如:当字符串为’We Are Happy.’则经过替换之后的字符串为’We%20Are%20Happy.’ 思考:基于python的特点, 如何对字符串进行替换操作?先看看字符串中有哪些常用方法。 观察到s.replace(old,new)可以对字符串进行替换 1s = 'we are happy.' 方法1. 利用python的语言特点作字符串替换 123class Solution: def replaceSpace1(self, s):#s为含空格字符串 return s.replace(\" \", \"%20\") 123method = Solution()answer = method.replaceSpace1(s)answer 'we%20are%20happy.'方法2. 从前往后遍历,依次替换空格 12345678class Solution: def replaceSpace2(self, s): s_new = \"\" for i in s: if i == \" \": i = \"%20\" s_new += i return s_new 123method = Solution()answer = method.replaceSpace2(s)answer 'we%20are%20happy.'1方法3. 12345678910class Solution: def replaceSpace3(self, s): s = list(s)#转换成列表 for i in range(len(s)): if s[i] == \" \": s[i] = \"%20\"# return s# return \" \".join(s)#用空格连接各个元素,返回如'w e %20 a r e %20 h a p p y .'# return \"_\".join(s)#用下划线'_'连接各个元素,返回如'w_e_%20_a_r_e_%20_h_a_p_p_y_.' return \"\".join(s)#不用空格或其他任何东西连接各个元素,返回如'we%20are%20happy.' 123method = Solution()answer = method.replaceSpace3(s)answer 'we%20are%20happy.'join的用法简单来说就是连接字符串。 join将容器对象拆分并以指定的字符将列表内的元素(element)连接起来,返回字符串(注:容器对象内的元素须为字符类型) https://www.cnblogs.com/hokky/p/8479991.html 与join相反,split以指定的字符将字符串分割为单个元素(字符类型)并加入list中,返回一个List reference: 1.https://blog.csdn.net/Datawhale/article/details/81944081 12","tags":[{"name":"剑指offer","slug":"剑指offer","permalink":"http://yoursite.com/tags/%E5%89%91%E6%8C%87offer/"},{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"面试题28:对称的二叉树","date":"2020-01-09T13:51:38.372Z","path":"2020/01/09/面试题28:对称的二叉树/","text":"题目:https://www.nowcoder.com/ta/coding-interviews 请实现一个函数,用来判断一颗二叉树是不是对称的。如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。 简单的考虑是: 1.比较树的根节点是否存在 2.根节点存在,则比较root.left?==root.right 3.若2成立,则针对两颗子树,判断 root1.left?==root2.right & root1.right?==root2.left,并不断重复这个过程 利用递归设计2-3(返回True或者False),在判断方法中调用 12345class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None 1234567891011121314class Solution: def isSymmetrical(self, pRoot): if not pRoot: return True return self.isSymmetricalTree(pRoot.left, pRoot.right) def isSymmetricalTree(self,root1,root2): if not root1 and not root2: return True if not root1 or not root2: return False if root1.val == root2.val: return self.isSymmetricalTree(root1.left,root2.right) and self.isSymmetricalTree(root1.right,root2.left) else: return False 参考:https://blog.csdn.net/u014568072/article/details/87913092 12","tags":[{"name":"剑指offer","slug":"剑指offer","permalink":"http://yoursite.com/tags/%E5%89%91%E6%8C%87offer/"},{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"面试题32:之字形打印二叉树","date":"2020-01-09T13:51:38.372Z","path":"2020/01/09/面试题32:之字形打印二叉树/","text":"题目:https://www.nowcoder.com/ta/coding-interviews?page=3 请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。 考虑:跟之前按行打印二叉树的思路,先将二叉树按行分别存入二维列表,然后将特定的子列表翻转 列表翻转: 1.https://www.runoob.com/python3/python-reversing-list.html 2.https://www.runoob.com/python3/python-slicing-rotate-string.html 12345678910#列表翻转a=[1,2,3,4,5,6,7,8,9] print(a) d=a[::-1]#对列表切片翻转print(a) c=aprint(d) c.reverse() #会改变原有列表print(c) print(a) #??为什么a会被改变 [1, 2, 3, 4, 5, 6, 7, 8, 9] [1, 2, 3, 4, 5, 6, 7, 8, 9] [9, 8, 7, 6, 5, 4, 3, 2, 1] [9, 8, 7, 6, 5, 4, 3, 2, 1] [9, 8, 7, 6, 5, 4, 3, 2, 1]123456def Reverse(lst): lst.reverse() return lst a=[1,2,3,4,5,6,7,8,9] print(Reverse(a)) [9, 8, 7, 6, 5, 4, 3, 2, 1]for循环步长:https://www.runoob.com/python3/python3-loop.html 12345#将索引为奇数(第偶数:2、4)个子列表翻转res = [[8], [6, 10], [5, 7, 9, 11], [12, 13]]for level in range(1, len(res), 2): res[level] = res[level][::-1]print(res) [[8], [10, 6], [5, 7, 9, 11], [13, 12]]12345class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None 123456789101112131415161718root = TreeNode(8)a = TreeNode(6)b = TreeNode(10)c = TreeNode(5)d = TreeNode(7)e = TreeNode(9)f = TreeNode(11)g = TreeNode(12)h = TreeNode(13) root.left = aroot.right = ba.left = ca.right = db.left = eb.right = fd.left = gd.right = h 12345678910111213141516171819202122class Solution: def Print(self, pRoot): if not pRoot: return [] result = [] level = 0 self.level(pRoot, level, result)#和之前一样,得到按行对应的二维列表 for level in range(1, len(result), 2):#将索引为奇数(第偶数:2、4)个子列表翻转 result[level] = result[level][::-1] return result def level(self, root, level, result):#和之前一样,得到按行对应的二维列表 if not root: return None if level == len(result): result.append([]) result[level].append(root.val) if root.left: self.level(root.left, level+1, result) if root.right: self.level(root.right, level+1, result) 123method = Solution()answer = method.Print(root)answer [[8], [10, 6], [5, 7, 9, 11], [13, 12]]参考:https://blog.csdn.net/fuxuemingzhu/article/details/79724959","tags":[{"name":"剑指offer","slug":"剑指offer","permalink":"http://yoursite.com/tags/%E5%89%91%E6%8C%87offer/"},{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"面试题15:二进制中1的个数","date":"2020-01-09T13:51:38.356Z","path":"2020/01/09/面试题15:二进制中1的个数/","text":"题目:https://www.nowcoder.com/ta/coding-interviews 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。 求整数的补码: 1、正整数的补码是其二进制表示,与原码相同; 例如:5(00000101) 2、负整数的补码:将其对应正数二进制表示所有位取反(包括符号位,0变1,1变0)后加1。 例如:-5对应正数5(00000101)→所有位取反(11111010)→加1(11111011) 根据补码求原码: 已知一个数的补码,则对应原码为:对该补码再求补码。 python中得到一个数n的补码:n & 0xffffffff(这个做法来自网络,具体原因未知),所以直接的做法如下: 12345class Solution1: def NumberOf1(self, n): if n < 0: n = n & 0xffffffff return bin(n).count('1') 123method = Solution1()answer = method.NumberOf1(-1)answer 32把一个整数减去1之后再和原来的整数做按位与,得到的结果相当于是把整数的二进制表示中最右边的一个1变成0,一个整数的二进制表示有多少个1则可以进行多少次这样的操作 根据上述特点可以得到一种求解方案,这也是《剑指offer》一书提供的精巧思路 123456789class Solution2: def NumberOf1(self, n): count = 0 if n < 0: n = n & 0xffffffff#得到负数的补码,计算机中负数以二进制补码形式存在 while n: n = n & (n-1) count += 1#count =count + 1 return count 123method = Solution2()answer = method.NumberOf1(-1)answer 32以下也是一种特别的方案,来自参考链接中的博主。 具体是:将负数-n转换为正n,然后计算(n-1)中的1的位数,再用32减之,刚好得到负数补码中1的位数 12345678class Solution3: def NumberOf1(self, n): if n>=0: count = bin(n).count('1') else: n=abs(n) count = 32 - bin(n-1).count('1')#和之前Solution2中的做法的联系是什么? return count 123method = Solution3()answer = method.NumberOf1(-1)answer 321bin(-11) '-0b1011'1bin(-11).replace('0b','') '-1011'移位操作:(确定位长) 12345678class Solution4: def NumberOf1(self, n): count = 0 for i in range(0,32): if n & 1:#与1做位与 count = count + 1 n = n >> 1#右移n,舍弃最右位,最左尾添0。右移一次,丢弃最右一个‘1’。 return count 123method = Solution4()answer = method.NumberOf1(-1)answer 32另一种移位操作:(确定位长) 123456789class Solution5: def NumberOf1(self, n): count = 0 operator = 1 for i in range(0, 32):#32位 if n & operator:#带判断数n与操作数operator做位与 count = count + 1 operator = operator << 1#操作数operator左移,而不是n右移。左移一次,消掉最右一个‘1’。 return count 123method = Solution5()answer = method.NumberOf1(-1)answer 32参考:1、https://blog.csdn.net/Datawhale/article/details/82182612 2、https://blog.csdn.net/fuxuemingzhu/article/details/79512764 12","tags":[{"name":"剑指offer","slug":"剑指offer","permalink":"http://yoursite.com/tags/%E5%89%91%E6%8C%87offer/"},{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"面试题27:二叉树的镜像","date":"2020-01-09T13:51:38.356Z","path":"2020/01/09/面试题27:二叉树的镜像/","text":"题目:https://www.nowcoder.com/ta/coding-interviews 操作给定的二叉树,将其变换为源二叉树的镜像。 思考: 反转根节点的左右子节点,这样把左右子节点带着的子树进行了调整;接下来对翻转后的左节点进行左右子节点的调整;翻转后的右节点操作同理; 当交换完所有非也节点的左右子节点后,就可以得到原树的镜像。 实际操作: 反转二叉树的左右节点,其实直接反转就好了:root.left,root.right = root.right, root.left 12345class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None 123456789class Solution: def Mirror(self, root): if not root: return None root.left,root.right = root.right, root.left if root.left: self.Mirror(root.left) if root.right: self.Mirror(root.right) 12","tags":[{"name":"剑指offer","slug":"剑指offer","permalink":"http://yoursite.com/tags/%E5%89%91%E6%8C%87offer/"},{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"面试题10:斐波拉契数列","date":"2020-01-09T13:51:38.340Z","path":"2020/01/09/面试题10:斐波拉契数列/","text":"题目:https://www.nowcoder.com/ta/coding-interviews 现在要求输入一个整数n; 输出斐波那契数列的第n项(从0开始,第0项为0)。n<=39 斐波那契数列 : 因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*) 方法1:直接利用递归的方法 这样的方法效率低,存在大量重复计算: 例如,想过要求得f(10)需要先求得f(9)、f(8);要求得f(9)要先求得f(8)、f(7)…如此等等。在剑指offer中给出了直观的依赖关系树形结构 12345678class Solution: def Fibonacci(self, n): if n<=0: return 0 elif n == 1: return 1 else: return self.Fibonacci(n-1)+ self.Fibonacci(n-2)#递归调用的写法!!!self.function 123method = Solution()answer = method.Fibonacci(8)answer 21解法2: 为了避免重复计算,可以选择从下往上计算,f(0)–>f(1)–>f(2)–>…–>f(10)…以此类推得到第n项。时间复杂度为O(n)。可以用数组存储,空间复杂度 O(n);也可以用变量存储,空间复杂度 O(1)。 12345678910111213class Solution1: def Fibonacci(self, n): if n<=0: return 0 elif n == 1: return 1 else: a = 0 b = 1 for i in range(2,n+1):#从第2到n b = a + b#更新b(当前非波拉契数列的值) a = b - a#a(保留前一个非波拉契数列的值) return b 123method = Solution1()answer = method.Fibonacci(8)answer 21方法3:利用python的相关特性 1234567891011class Solution2: def Fibonacci(self, n): if n<=0: return 0 if n==1: return 1 else: a,b=0,1 for i in range(n-1):#循环n-1次 a,b=b,a+b#a的变化?先计算右边的值再同时赋值给左边 return b 先将b赋予a;再更新b,跟Solution1中的方法相似 123method = Solution2()answer = method.Fibonacci(3)answer 2利用列表来实现是我感觉很赞的方法,最直观明了 1234567891011class Solution3(): def Fibonacci(self, n): a = [0, 1] if n<=0: return a[0] if n==1: return a[n] else: for i in range(2, n+1): a.append(a[i-1] + a[i-2]) return a[n] 123method = Solution3()answer = method.Fibonacci(8)answer 21参考: https://blog.csdn.net/fuxuemingzhu/article/details/79501434 https://blog.csdn.net/Datawhale/article/details/82152447 https://doocs.gitee.io/coding-interview/#/docs/coding-interview 12","tags":[{"name":"剑指offer","slug":"剑指offer","permalink":"http://yoursite.com/tags/%E5%89%91%E6%8C%87offer/"},{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"面试题10:跳台阶","date":"2020-01-09T13:51:38.340Z","path":"2020/01/09/面试题10:跳台阶/","text":"题目:https://www.nowcoder.com/ta/coding-interviews 这是在“面试题10:非波拉契数列”中的另一个题目 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。 理解: 如果有1级台阶,只有1种 ;如果有2级台阶,有1–1、2两种 ;如果有3级台阶,有1–1–1、1–2、2–1三种跳法 假设n级台阶有F(n)种跳法,一定是先跳1级或者先跳2级这两类方式,再继续跳到n级台阶,跳1级后有F(n-1)种,跳2级后有F(n-2)种,故共有F(n)=F(n-1)+F(n-2)。这与斐波拉契数列一致。 但是跳台阶没有0级台阶:F(1)=1,F(2)=2,F(3)=3,F(4)=5,…,F(n)=F(n-1)+F(n-2),… 12345678910111213class Solution1: def jumpFloor(self, number): if number == 1: return 1 elif number == 2: return 2 else: a = 1 b = 2 for i in range(2,number): b = a + b a = b - a return b 123method = Solution1()answer = method.jumpFloor(5)answer 8123456789101112class Solution: def jumpFloor(self, number): if number == 1: return 1 elif number == 2: return 2 else: a = 1 b = 2 for i in range(2,number): a,b = b,a+b return b 123method = Solution()answer = method.jumpFloor(5)answer 812","tags":[{"name":"剑指offer","slug":"剑指offer","permalink":"http://yoursite.com/tags/%E5%89%91%E6%8C%87offer/"},{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"面试题11:旋转数组的最小数字","date":"2020-01-09T13:51:38.340Z","path":"2020/01/09/面试题11:旋转数组的最小数字/","text":"题目:https://www.nowcoder.com/ta/coding-interviews 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。 思考: 利用旋转数组的特性来设计查找最小值的方法。 原数组是非递减排序的,旋转数组可划分为两个非递减子数组,并且前面子数组的元素都>=后面子数组的元素,最小元素恰好是两个数组的分界线; 暴力的o(n)查找 12345678910class Solution1: def minNumberInRotateArray(self, rotateArray): min = rotateArray[0] if len(rotateArray)==0: return 0 else: for i in range(1,len(rotateArray)): if rotateArray[i] < min: min = rotateArray[i] return min 123rotateArray = [4, 5, 6, 1, 2, 3]method = Solution1()method.minNumberInRotateArray(rotateArray) 11234# for i in range(0,5):#不会包含最后一个索引,左闭右开# print(i)# for i in range(0,len(rotateArray)):# print(rotateArray[i]) 根据旋转数组的特性设计二分查找: 1.设置中间点,标记旋转数组首元素和尾元素,中间点将数组分成两半; 2.如果中间点大于等于首元素,说明最小数字在数组后一半,如果中间点小于等于尾元素,说明最小数字在数组前一半; 3.依次改变首、尾元素的位置,当尾元素和首元素挨着的时候,这时候尾元素就是所找的最小值。 123456789101112131415class Solution2: def minNumberInRotateArray(self, rotateArray): left = 0 right = len(rotateArray)-1 if len(rotateArray)==0: return 0 else: while(right - left) > 1: mid = (left + right)//2#商向下取整的结果 if rotateArray[mid] >= rotateArray[left]:#中间值在第一组比左大,最小值在mid右 left = mid#更新左 elif rotateArray[mid] <= rotateArray[right]:#中间值在第二组比右小,最小值在mid左 right = mid#更新右 return rotateArray[right]#右元素为最小 #当不满足while条件时,说明数组有两个元素(或者一个元素),直接返回旋转数组右边元素即可 123rotateArray = [4, 5, 6, 1, 2, 3]method = Solution2()method.minNumberInRotateArray(rotateArray) 1特殊的是,当首元素等于尾元素等于中间值时,以上比较规则失效,只能对数组进行顺序查找,增加如下判断: 12345678910111213141516171819202122class Solution3: def minNumberInRotateArray(self, rotateArray): left = 0 right = len(rotateArray)-1 if len(rotateArray)==0: return 0 else: while(right - left) > 1: mid = (left + right)//2#商向下取整的结果 if rotateArray[mid] == rotateArray[left] and rotateArray[mid] == rotateArray[right]: #特殊情况,当首元素等于尾元素等于中间值时,只能对数组进行顺序查找 min = rotateArray[left] for i in range(left,right): if rotateArray[i] < min: min = rotateArray[i] return min elif rotateArray[mid] >= rotateArray[left]:#中间值在第一组比左大,最小值在mid右 left = mid#更新左 elif rotateArray[mid] <= rotateArray[right]:#中间值在第二组比右小,最小值在mid左 right = mid#更新右 return rotateArray[right]#右元素为最小 #当不满足while条件时,说明数组有两个元素(或者一个元素),直接返回旋转数组右边元素即可 1234# rotateArray = [4, 5, 6, 1, 2, 3]rotateArray = [ 0, 1, 1]method = Solution3()method.minNumberInRotateArray(rotateArray) 1剑指offer书中还考虑到旋转数组旋转了0个元素的情况,也就是排序数组本身:第一个元素(左)就是最小的元素 123456789101112131415161718192021222324class Solution: def minNumberInRotateArray(self, rotateArray): left = 0 right = len(rotateArray)-1 if len(rotateArray)==0: return 0 elif rotateArray[left] < rotateArray[right]: return rotateArray[left] else: while(right - left) > 1: mid = (left + right)//2#商向下取整的结果 if rotateArray[mid] == rotateArray[left] and rotateArray[mid] == rotateArray[right]: #特殊情况,当首元素等于尾元素等于中间值时,只能对数组进行顺序查找 min = rotateArray[left] for i in range(left,right): if rotateArray[i] < min: min = rotateArray[i] return min elif rotateArray[mid] >= rotateArray[left]:#中间值在第一组比左大,最小值在mid右 left = mid#更新左 elif rotateArray[mid] <= rotateArray[right]:#中间值在第二组比右小,最小值在mid左 right = mid#更新右 return rotateArray[right]#右元素为最小 #当不满足while条件时,说明数组有两个元素(或者一个元素),直接返回旋转数组右边元素即可 123456rotateArray = [ 0, 1, 1, 1]# rotateArray = [ 1, 0, 1, 1, 1,]# rotateArray = [ 1, 1, 1, 0, 1]# rotateArray = [4, 5, 6, 1, 2, 3]method = Solution()method.minNumberInRotateArray(rotateArray) 0这里补充另一位博主的写法Solution4 1234567891011121314151617181920212223242526# -*- coding:utf-8 -*-class Solution4: def minNumberInRotateArray(self, rotateArray): p1, p2 = 0, len(rotateArray) - 1#一样的操作固定首尾 mid = p1#特殊情况下的最小值索引,即对应之前的旋转为0的旋转数组。结合下列循环条件来看,我觉得这里很精彩 while rotateArray[p1] >= rotateArray[p2]:#和之前用索引大小来确定循环不同,这里直接用首元素>=尾元素这个特性来确定循环 if p2 - p1 == 1:#首尾相邻,尾小,即为最小值 mid = p2#最后统一返回mid索引下的元素 break# mid = (p1 + p2) / 2#原博主写法 mid = (p1 + p2) // 2#这里我觉得应该是取整才对 if rotateArray[mid] == rotateArray[p1] and rotateArray[mid] == rotateArray[p2]: return self.minInOrder(rotateArray, p1, p2)#特殊情况,判断失效,只能遍历 if rotateArray[mid] >= rotateArray[p1]: p1 = mid elif rotateArray[mid] <= rotateArray[p2]: p2 = mid return rotateArray[mid]#最终p2会停留在mid上,写作rotateArray[p2]也没有区别,这里整段代码都统一返回mid索引值 def minInOrder(self, nums, index1, index2):#确定首尾,遍历一段数组,得到最小值# n1 = nums[index]#原博主写法 n1 = nums[index1]#应改为 for i in range(index1 + 1, index2): if n1 > nums[i]: return nums[i] return n1 123456# rotateArray = [ 0, 1, 1, 1]# rotateArray = [ 1, 0, 1, 1, 1]# rotateArray = [ 1, 1, 1, 0, 1]rotateArray = [4, 5, 6, 1, 2, 3]method = Solution4()method.minNumberInRotateArray(rotateArray) 1参考: https://blog.csdn.net/Datawhale/article/details/82143776 https://blog.csdn.net/fuxuemingzhu/article/details/79501202","tags":[{"name":"剑指offer","slug":"剑指offer","permalink":"http://yoursite.com/tags/%E5%89%91%E6%8C%87offer/"},{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"有关ubuntu的琐碎小事儿","date":"2020-01-09T13:51:38.325Z","path":"2020/01/09/有关ubuntu的琐碎小事儿/","text":"1.安装电子书阅读器: 1sudo apt install fbreader 2.安装谷歌访问助手 a.百度下载谷歌访问助手 .crx **文件,将其重命名为.zip文件,然后解压; b.打开,将其中_metadata文件重命名为metadata**; c.chrome浏览器打开拓展程序界面开发者模式,加载已解压文件夹,done.3.Ubuntu中python版本切换 a.ubuntu中将python3设置为默认,执行: 12sudo update-alternatives --install /usr/bin/python python /usr/bin/python2 100sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 150 b.ubuntu中将python2设置为默认,执行: 1sudo update-alternatives --config python","tags":[{"name":"Ubuntu","slug":"Ubuntu","permalink":"http://yoursite.com/tags/Ubuntu/"}]},{"title":"面试题10:变态跳台阶","date":"2020-01-09T13:51:38.325Z","path":"2020/01/09/面试题10:变态跳台阶/","text":"题目:https://www.nowcoder.com/ta/coding-interviews?page=1 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。 理解: 跟之前的分析有相似的地方,假设跳n级台阶有F(n)种方式,那么可能的情况有,先跳1级、或者先跳2级、或者先跳4级、…、或者先跳n-1级、或者直接跳到n级. 相应的:先跳1级后有F(n-1)种,先跳2级后有F(n-2)种,…,跳n-1级有F(1)种,值得注意的是直接跳到n级台阶为1种 于是:F(n)=F(n-1)+F(n-2)+F(n-3)+…+F(3)+F(2)+F(1)+1 1234567891011121314class Solution1: def jumpFloorII(self, number): a = [1,2] if number <= 0: return 0 elif number == 1: return 1 elif number == 2: return 2 else: for i in range(2, number):#i仅仅代表需要操作的次数 ai = 1 + sum(a) a.append(ai) return a[number-1]#索引值(从0开始)比实际台阶数小1 123method = Solution1()answer = method.jumpFloorII(5)answer 16根据递推公式:$F(n)=2^{(n-1)}$ 123456class Solution2: def jumpFloorII(self, number): if number <= 0: return 0 else: return 2**(number-1) 123method = Solution2()answer = method.jumpFloorII(5)answer 1612","tags":[{"name":"剑指offer","slug":"剑指offer","permalink":"http://yoursite.com/tags/%E5%89%91%E6%8C%87offer/"},{"name":"python","slug":"python","permalink":"http://yoursite.com/tags/python/"}]},{"title":"搭建Hexo博客并部署到Github","date":"2020-01-09T13:51:38.309Z","path":"2020/01/09/搭建Hexo博客并部署Github/","text":"这是zongpu搭建个人博客的过程记录 工具windows, Git, Node 安装Hexo 利用 npm 命令即可安装。在任意位置点击鼠标右键,选择Git Bash Here。 输入命令:npm install -g hexo 注意:-g是指全局安装hexo。 创建Hexo文件夹安装完成后,在你喜爱的文件夹下(如C:\\Hexo),执行以下指令(在C:\\Hexo内点击鼠标右键,选择Git Bash),Hexo 即会自动在目标文件夹建立网站所需要的所有文件。 hexo init 安装依赖包npm install 本地查看Hexo博客现在我们已经搭建起本地的hexo博客了,执行以下命令(在C:\\Hexo),然后到浏览器输入localhost:4000看看。 hexo generate hexo server 注:因为4000端口占用的原因,我在这里并不能打开本地博客 切换端口以解决在Hexo文件夹下的_config.yml文件内增加端口服务设置(以切换到5000为例) #Server server: port: 4000 compress: true header: true 运行如图: Github创建仓库创建的时候注意Repository的名字。比如我的Github账号是zongpu,那么我应该创建的Repository的名字是:zongpu.github.io这是特别的约定。 到你刚刚创建的Repository下,找到以下内容: 在仓库里找到HTTPS,复制里面的地址。 然后编辑_config.yml文件(在C:\\Hexo下),修改增加内容如下(修改时,冒号后面需要空格): deploy: type: git repository: https://github.com/zongpu/zongpu.github.io.git branch: master 并保存。 设置SSHKEYs 在Git Bash输入以下指令(任意位置点击鼠标右键),检查是否已经存在了SSH keys。 ls -al ~/.ssh 如果不存在就没有关系,如果存在的话,直接删除.ssh文件夹里面所有文件: 输入以下指令(邮箱就是你注册Github时候的邮箱)后,回车: ssh-keygen -t rsa -C “[email protected]“ 经过几次回车会看到方框状的 key’s randomart image 其中,会提示要你输入passphrase(如上图,我没有输入直接回车,如果你输入的话,要记得,到时候会用到)。之后,如果出现类似下图: 然后键入以下指令: ssh-agent -s 继续输入指令: ssh-add ~/.ssh/id_rsa 输入之后,在我这里是出错了,不知道你的有没有出错。 如果你的也是这样子出错了的话,就输入以下指令:(由于编辑格式的原因,这里是:’ssh-agent -s‘,有单引号) eval ssh-agent -s ssh-add 6. 到了这一步,就可以添加SSH key到你的Github账户了。键入以下指令,拷贝Key(先拷贝了,等一下可以直接粘贴): clip < ~/.ssh/id_rsa.pub 注:这里也可以在.ssh文件夹里找到id_rsa.pub文件并复制里面的内容。 7. 然后到Github里面,找到设置:![1532755228554](C:\\Users\\Zhou\\AppData\\Local\\Temp\\1532755228554.png) 添加新的SSH keys 这里title可作为一个key的说明,key值,刚才已经用命令行复制,可直接粘贴,保存,添加。 最后还是测试一下吧,键入以下命令: ssh -T [email protected] 你可能会看到有警告,没事,输入“yes”就好。 完成部署 最后一步,快要成功了,键入指令: hexo generate hexo deploy OK,我们的博客就已经完全搭建起来了,在浏览器输入(当然,是你的用户名): http://xxx.github.io/ 当然:理想是饱满的,在这里又出现了错误 a. 经搜索错误Error: fatal: HttpRequestException encountered. 了解到,是Github 禁用了TLS v1.0 and v1.1,必须更新Windows的git凭证管理器 :GCMW(下载链接:https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases/tag/v1.14.0) 出处:https://blog.csdn.net/txy864/article/details/79557729 b. 或者键入: git config –global credential.helper manager 重新发布,也能正常push:https://blog.csdn.net/u010229836/article/details/78229339 注意:每次修改本地文件后,需要键入hexo generate才能保存。每次使用命令时,都要在C:\\Hexo目录下。每次想要上传文件到Github时,就应该先键入hexo generate保存之后,再键入hexo deploy。大概成功之后是酱紫的: 对了,记住上图的Username是你的Github账号名称,而不是邮箱;Password就是你的Github的密码。 博客主题修改官方主题地址为hexo-themes 命令格式:git clone https://github.com/litten/hexo-theme-yilia.git themes/yilia ![1532771944857](C:\\Users\\Zhou\\AppData\\Local\\Temp\\1532771944857.png) ## 一个问题:Hexo的版本控制与持续集成 参见博客:https://formulahendry.github.io/2016/12/04/hexo-ci/ 最后,以上内容部分截图、陈述来自互联网,实在是做的时候自己没留意截图,在此致谢! 主要参考了如下博客,自己也留作参考: 1. https://lishion.github.io/2018/06/07/%E4%BD%BF%E7%94%A8git+hexo%E5%BB%BA%E7%AB%8B%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/ 2. https://jingyan.baidu.com/article/d8072ac47aca0fec95cefd2d.html 3. https://www.jianshu.com/p/189fd945f38f 4. https://blog.csdn.net/loveyouluobin/article/details/80037108 5. https://www.jianshu.com/p/1537f3fffe63 6. https://www.jianshu.com/p/8681ab76da08 7. https://blog.csdn.net/ainuser/article/details/77609180 8. https://www.jianshu.com/p/189fd945f38f","tags":[{"name":"Hexo","slug":"Hexo","permalink":"http://yoursite.com/tags/Hexo/"}]},{"title":"修改jupyter notebook默认工作路径","date":"2020-01-09T13:51:38.293Z","path":"2020/01/09/修改jupyter-notebook默认工作路径/","text":"1.生成配置文件在工作虚拟环境下执行: 1jupyter-notebook --generate-config 2.在配置文件中修改/设置默认路径打开配置文件 1code ~/.jupyter/jupyter_notebook_config.py 搜索找到以下字段 1#c.NotebookApp.notebook_dir = '' 取消注释并在‘’中填入想要的工作路径,例如: 1c.NotebookApp.notebook_dir = /home/zongpu/AnacondaProjects","tags":[{"name":"jupyter notebook","slug":"jupyter-notebook","permalink":"http://yoursite.com/tags/jupyter-notebook/"}]},{"title":"初次提交项目到Github","date":"2020-01-09T13:51:38.293Z","path":"2020/01/09/初次提交项目到Github/","text":"这是初次使用github提交项目的几个简单操作记录(忽略仓库建立过程) 初次提交项目到仓库1.在项目文件所在路径下右键唤出git bash 2.执行git init ,在当前项目的目录中生成本地的git管理(会发现在当前目录下多了一个.git文件夹); 3.输入git add . (空格点表示将所有的文件添加到仓库中 ),不然,则将“.”换成要提交的文件名即可; 4.执行git commit -m “first commit”,表示你对这次提交的注释,双引号里面的内容可以根据提交的情况修改; 5.在次执行git commit -m “first commit”时就会成功 (我忘记是否有这步),提交时试试即可,不影响; 6.执行git remote add origin https://自己的仓库url地址 (打开要提交到的github仓库即可寻到)关联仓库; 7.执行git push -u origin master命令即可提交到仓库; 另外:在本地git没有关联到github账号时上述步骤中有需要输入github账号、密码的情况。 参考博客:https://blog.csdn.net/m0_37725003/article/details/80904824 更新本地项目后提交到github1.查看当前的git仓库状态,可以使用git status 2.更新git add (项目文件或者用“.”表示路径下的全部) 3.接着执行git commit -m “更新说明” 4.执行git pull拉取当前分支更新情况 5.执行git push origin master push到远程master分支上 参考博客:https://www.cnblogs.com/zlxbky/p/7727895.html","tags":[{"name":"Github","slug":"Github","permalink":"http://yoursite.com/tags/Github/"}]},{"title":"Ubuntu18.04深度学习GPU环境配置","date":"2020-01-09T13:51:38.278Z","path":"2020/01/09/Ubuntu18.04深度学习GPU环境配置/","text":"主要环节:Ubuntu18.04(已安装好)、CUDA安装、cuDNN安装、Anaconda设置虚拟环境安装TF等背景:在经过过漫长的小论文准备实验和写作后,终于将稿子交与导师审校,想来也有时间可以学习盼望已久的东西了。在经历一整天反复折腾后,结合几篇博客对每一步进行稍作记录,作为备忘的同时也许可以帮到其他萌新。 1 版本选择CUDA10.0+cuDNN7.5.0 for CUDA10.0 官网: cuda:https://developer.nvidia.com/cuda-10.0-download-archive?target_os=Linux&target_arch=x86_64&target_distro=Ubuntu&target_version=1804&target_type=runfilelocal cudnn(需要先注册账户):https://developer.nvidia.com/rdp/cudnn-download 2 安装显卡NVIDIA显卡驱动这里本来以前我通过在官网下载run文件安装过,但是稍显麻烦也忘了具体流程,于是参考别人的做法用了ppa源的安装方式 2.1 卸载原有驱动12# 删除sudo apt-get purge nvidia* 2.2 禁止自带驱动12# 打开配置文件sudo vim /etc/modprobe.d/blacklist-nouveau.conf 将以下字段添加到文件末尾 12blacklist nouveauoptions nouveau modeset=0 更新文件 1sudo update-initramfs -u 这里可能需要重启电脑 12# 重启sudo reboot 2.3 添加Graphic Drivers PPA12sudo add-apt-repository ppa:graphics-drivers/ppasudo apt-get update 查看合适的驱动版本以安装 1ubuntu-drivers devices 如图: 我选择推荐的418版本安装: 1234# 安装sudo apt-get install nvidia-driver-396# 重启sudo reboot 安装成功后会显示显卡信息: 12sudo nvidia-smisudo nvidia-settings 以上便安装好了显卡驱动。 3 安装CUDA3.1 下载CUDA10.0 以上是我的选择情况。 3.2 安装依赖关系参考:https://www.cnblogs.com/Ph-one/p/9000211.html 1sudo apt-get install freeglut3-dev build-essential libx11-dev libxmu-dev libxi-dev libgl1-mesa-glx libglu1-mesa libglu1-mesa-dev 3.3 降低GCC版本根据诸多博客的经验,还需要先降低GCC版本,先查看: 1234#查看版本信息gcc --version#或者g++ --version 安装低GCC版本(多数博客均是该版本): 1234sudo apt install gcc-5 g++-5#或者sudo apt-get install gcc-5sudo apt-get install g++-5 根据提示开始安装低版本 然后替换: 12sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 50 # you will find that message that tells you the gcc-5 is set to be automatic.sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 50 # similiar message as gcc 值得一提的是文章https://blog.csdn.net/sinat_40276791/article/details/80403784中提到说:**安装cuda的时候并没有降级gcc,g++;说明cuda9.0已经支持gcc7.0安装,所谓降级是后面要编译cuda测试例子的时候用到6.0以下的g++,和gcc版本。**但是我的gcc版本较高,为保险,我还是先降低。 3.4 开始安装CUDA1sudo sh cuda_10.0.130_410.48_linux.run ctrl+c 可快速结束阅读文档接下来根据提示选择就好了, 值得一提的是,在安装过程中会提示是否需要安装显卡驱动,这里要选择n,因为我们已经提前安装了驱动,提前安装驱动也是几乎所有博主的选择,我并没有单独尝试不提前安装的情况。其他的选择y或者回车键进行安装即可。 3.5设置环境变量:1sudo gedit ~/.bashrc 在打开的文本中添加下列内容,根据版本进行改动 12export PATH=/usr/local/cuda-10.0/bin${PATH:+:${PATH}} export LD_LIBRARY_PATH=/usr/local/cuda-10.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} 更新: 1source ~/.bashrc 也许需要重启 3.6 测试是否成功验证CUDA10.0是否安装成功: 123456# 第一步,进入例子文件cd /usr/local/cuda-10.0/samples/1_Utilities/deviceQuery# 第二步,执行make命令sudo make# 第三步./deviceQuery 输出结果有GPU的信息,以及显示Result = PASS等,说明CUDA安装成功。 4 安装cuDNN4.1 cuDNN下载 下载对应的Deb文件,这里对应Ubnuntu18.04共有三项,都要下载。 4.2 安装注意:这里有的博客直接下载了cuDNN Library for Linux项,安装方式有所不同(这在官网也有安装说明),如下: 12345678#1.Navigate to your <cudnnpath> directory containing the cuDNN Tar file.#2.Unzip the cuDNN package.$ tar -xzvf cudnn-9.0-linux-x64-v7.tgz#3.Copy the following files into the CUDA Toolkit directory, and change the file permissions.$ sudo cp cuda/include/cudnn.h /usr/local/cuda/include$ sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64$ sudo chmod a+r /usr/local/cuda/include/cudnn.h $ sudo chmod a+r /usr/local/cuda/lib64/libcudnn* 官网安装说明:https://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html#installlinux 之前已经下载好了文件(对应的三项),我现在直接安装: 123sudo dpkg -i libcudnn7_7.5.0.56-1+cuda10.0_amd64.debsudo dpkg -i libcudnn7-dev_7.5.0.56-1+cuda10.0_amd64.debsudo dpkg -i libcudnn7-doc_7.5.0.56-1+cuda10.0_amd64.deb 4.3 测试执行以上命令后,测试是否安装好: 1234cp -r /usr/src/cudnn_samples_v7/ $HOMEcd $HOME/cudnn_samples_v7/mnistCUDNNmake clean && make./mnistCUDNN 最终显示Test passed!则安装成功 版本查看 1nvcc -V 以上是cuDNN的安装。 5 安装Anaconda5.1 安装anacondaAnaconda的优点有口皆碑,安装也十分方便,根据不同版本选择修改即可: 1bash Anaconda3-5.3.0-Linux-x86_64.sh 5.2 更改pip和conda为国内的源1mkdir ~/.pip 12345cat > ~/.pip/pip.conf << EOF[global]trusted-host=mirrors.aliyun.comindex-url=https://mirrors.aliyun.com/pypi/simple/EOF 12conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/conda config --set show_channel_urls yes 5.3 为TF准备虚拟环境12conda create --name tensorflow python=3.6 #创建tf环境,这里我的虚拟环境名字叫tensorflow,根据喜好替换即可 一些常用命令: 12345source activate tensorflow #激活环境#或者conda activate tensorflow #激活环境source deactivate tensorflow #退出环境#conda deactivate tensorflow #退出环境conda remove --name tensorflow --all #删除tensorflow环境(全部删除) 5.4 安装Tensorflow进入虚拟环境后再进行安装: 1234conda activate tensorflow# 安装 gpu 版本的 tensorflow 和 kerasconda install tensorflow-gpu # 默认安装最新版本conda install keras 命令将会自动安装相关组件,如:numpy 、wheel 、tensorflow-tensorboard 、six、protobuf 、html5lib 、markdown、werkzeug 、bleach、setuptools等。 5.6 测试进入虚拟环境,找到python: 12source activate tfpython 在Python命令下: 1234import tensorflow as tfhello= tf.constant('Hello, TensorFlow!')sess= tf.Session()print(sess.run(hello)) 如果没有报错则安装成功。 5.7 其他框架:同样在我们设置的虚拟环境内: 12#安装Kerasconda install keras 1234567#安装Pytorchconda install pytorch torchvision -c pytorch#测试source activate tfpythonimport torchprint(torch.cuda.is_available()) 参考anaconda安装详细过程:https://blog.csdn.net/u012318074/article/details/77074665 机器学习初学者文章(Ubuntu 18.04深度学习环境配置(CUDA9.0+CUDDN7.4+TensorFolw1.8)): https://mp.weixin.qq.com/s?__biz=Mzg5NzAxMDgwNg==&mid=2247483901&idx=1&sn=f02bd7866ad172ef0c9669851dffde2a&chksm=c0791ce4f70e95f2343047e62d513c0106eedebc09cc25d1c45598ede21da8655a974c6a69c5&mpshare=1&scene=1&srcid=04179jALGhka70U7n9ovBuKY&pass_ticket=KprLcHSq%2F%2FifAFYAESWtIOC2CUJ3iHrXGxrel4jNTybt4taMs41OkZkLKgYztL0x#rd Ubuntu18.04深度学习GPU环境配置:https://blog.csdn.net/weixin_41863685/article/details/80303963","tags":[{"name":"Tensorflow","slug":"Tensorflow","permalink":"http://yoursite.com/tags/Tensorflow/"}]},{"title":"Hello World","date":"2020-01-09T13:51:38.278Z","path":"2020/01/09/hello-world/","text":"Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. Quick StartCreate a new post1$ hexo new \"My New Post\" More info: Writing Run server1$ hexo server More info: Server Generate static files1$ hexo generate More info: Generating Deploy to remote sites1$ hexo deploy More info: Deployment","tags":[]},{"title":"2019开始躺平","date":"2020-01-09T13:51:38.262Z","path":"2020/01/09/2019,开始躺平/","text":"这是2020元旦时候发布在微信公众号上的随笔,原文搬运到了博客。 “这是酝酿了很久的表达,倒不是为了圆一个少不经事的梦,他既没丰富阅历也无多少奇思妙想,只是想试着记录一颗沙砾在生活的泥泞中如何挣扎。所以,这不是什么正经写作,所有的文字都只是一时兴起而已。” 公历2019已经到了尾声,你度过了快乐的一年么?但其实不快乐也没什么关系。对于绝大多数人而言,过去的每一年都只是一个工具人生命中最普通的一年。在时间尺度上,你既抓不住太阳光射向地球的某一瞬,也感受不到千百年为周期的星轨变化,你看到的都只是历史,是事物消逝前的余光;在空间尺度上,你倒是能体会到一些,比如怎么也穿不进的裤子,端倪初现的颈椎,没有归属感的城市,你感受到的是活生生的当下,是把握不住的遗憾。理智告诉你再丧下去将万劫不复,于是开始寻求正能量,可什么又是正能量呢?鸡汤一碗一碗干?健身旅行学英语,电影阅读走走看?我选择躺平,追求简单的快乐也接受不快乐,傻傻地活着。所以,把我喜欢的分享给小伙伴儿们呀,除了获得一点儿快乐,分享还可以满足虚荣心不是么? 01 — 喜欢的书 《别闹了,费曼先生》/《你干嘛在乎别人怎么想》 ——理查德·费曼 img img “这是我早些年应该看的书,不过谁知道现在看算不算晚呢” “我无法寄出这封信,因为我已不再知道你的地址” 《果壳中的宇宙》 ——史蒂芬·霍金 img “思想形成人的伟大。人只不过是一根苇草,是自然界最脆弱的东西,但他是一根能思想的苇草。用不着整个宇宙都拿起武器来才能毁灭他,一口气、一滴水就足以致他死命了。然而,纵使宇宙毁灭了他,人却仍然要比致他于死命的东西高贵得多,因为他知道自己要死亡,以及宇宙对他所具有的优势,而宇宙对此却是一无所知。因而,我们全部的尊严就在于思想。正是由于它而不是由于我们所无法填充的空间和时间,我们才必须提高自己。因此,我们要努力好好地思想。这就是道德的原则。——《人是一根能思想的芦苇(Man is a reed that thinks)》帕斯卡” 之所以看这本书是因为看到新闻说霍金合作者在预印本网站发出了霍金生前最后的工作,相比只能用来装点书架的硬核科普《时间简史》,这本书只是科学家的几篇讲稿一点哲思。“庐山的如琴湖畔提供了当今已经非常稀罕的清静,使我在一个多月内得以专心译述。窗外云雾晴岚、朝晖夕霞瞬息变幻。奇峰异壑、飞瀑流泉间遍布着王羲之、慧远、陶潜、李白、白居易、苏轼和王阳明的遗迹,这一切予人以无限的想象空间。在这种氛围中思索宇宙是再惬意不过的了。——吴忠超” 另外,大刘的《朝闻道》也十分推荐,在时间的尺度上,与思想萌芽所需相比,实现它只不过是一瞬。通过科学这项人类最伟大的事业,即使被禁锢在果壳之内,人仍然可以享有精神的自由。不过,有一天当你收到那个信息的时候请不要回答!不要回答!不要回答! 《这里是中国》 ——星球研究所 / 中国青藏高原研究会 img “中国从哪里来?将往何处去?” 阅读这本书是因为我非常喜欢星球研究所公众号,你未必能触及中国的每一寸土地,但有另一种阅尽中国的希望。另外,直接打动我的大概是文章中的每一幅配图吧。 img 贡嘎山倒影 img 方脸藏狐 img 连通伊犁河谷与北疆的果子沟大桥 《曙光集》/《晨曦集》/《近代科学进入中国的回顾与前瞻》 ——杨振宁 img img ”The party is over” 评价一个科学家首先应该了解的是他的科学成就,以及真正的贡献,而不是八卦。 一直以来我都愿意看科幻、科普作品,除了“科技让生活更美好”的口头禅外,这一年实实在在地受到了工业党思维的冲击,算是多了一些情怀。其实除了上面那些闲书,翻得最多的应该是《矩阵分析》和乱七八糟的论文,“人工智能四大名著”也是心头好,只是他们都颇有难度,废柴如我是没能完全读下去的,只能被疯狂劝退,让我时不时点开无脑小说金庸全集。当然我也不能一字一句读完金庸,毕竟好看的也没有几章,以现在的价值观来看全员渣,可能是作者亲身有过愧疚德损,只好动不动就平安喜乐。 02 — 喜欢的影视剧 《绝杀慕尼黑》 img 气氛非常苏,剧情类似《摔跤吧,爸爸》,俄罗斯爱国电影,看的时候也若有若无的感到这是俄罗斯在缅怀那个强大的年代吧,即使她有不好的一面。另外,背景虽然严肃,但是有很多舒缓的情节,时不时穿插苏式幽默,不看重背景就是单纯的运动片,边喝快乐水边欣赏比赛也无违和感。因为时代的局限,我们对那个两雄并立年代的认识是断层的,他们不只是爱喝伏特加,他们也有出众的文学艺术,如同我们自己失去的那些年。 《寄生虫》 img 借助完备的电影工业体系,韩国人之前拍了太多这种类型的电影,还好我在看的时候没有产生疲劳,这有赖于导演营造的阴森气氛使人清醒清醒。总体给人的感觉不是感官刺激上的害怕,是讽刺癫狂更是难以摆脱的宿命轮回般的绝望。导演奉俊昊作品风格也是多变的,我看过他之前的作品有灾难丧尸类的《汉江怪物》、《雪国列车》,也有剧情悬疑向的《杀人回忆》,但总体都偏阴暗。 《我的大叔》 img 2018年豆瓣年末盘点的时候**《我的大叔》**在韩剧榜首,看了简介觉得喜欢而且还短,就在春节的时候看了,但其实片子的气质跟春节一点儿都不匹配。每个人都愁眉苦脸,估计跟那时候的我差不多,于是就看了。忽略掉一些技术上的不合理,垃圾的人生才需要这种东西安慰自己吧,另外配乐也很棒。 어른 Sondia - 나의 아저씨 OST img img 结尾风格是这样的,还算不错。 另外在某天逛知乎的时候,看到了大约是“哪个影视片段令你印象深刻?”的话题,下面有个抖机灵的回答成功引起了我的注意,于是就找找到了 《电影少女》 img 没错,片子类型大约是“死宅的幻想”,无聊透顶还恰好有眼缘的可以看看,不长。有趣的是上面开头的两部片子都在今年的豆瓣年度电影榜单之列,算是小小的惊喜。 03 — 喜欢的音乐 Alison Krauss img When You Say Nothing At All Alison Krauss - Now That I’ve Found You: A Collection img 大佬的歌几乎都好听的列表循环就对了 IU img 通常来说,这不是我喜欢的听歌类型,但还是听了不少, 大概是因为听了能让人轻快起来。 日常循环的就是李宗盛、周杰伦和李健了,流行音乐居多,也喜欢乡村和民谣,我不是很能分清楚他们的区别,不过我能明显的感受到歌词的好坏,不喜欢故作“民谣”式的嗓子,喜欢自然的表达。今年其实还听了不少摇滚,可能是无形中受到了电影《波西米亚狂想曲》的影响,也可能脑海中常常回想起的《带我去月球》。还特别喜欢电影《白日梦想家》的插曲 Stay Alive José González - Stay Alive img Space Oddity David Bowie;Kristen Wiig - The Secret Life Of Walter Mitty img Don’t You Want Me Bahamas;The Weather Station - The Secret Life Of Walter Mitty img 暑假回校那段时间常听的还有土嗨伍佰 夏夜晚风 伍佰 & China Blue - 爱你伍佰年 img 04 — 偶然遇到的诗 跑着的云 告诉蓝天 你要晚一点走 孩子们还没有回家 ——《等等》 “平凡枯燥的生活孕育的诗意是渴望。这是诞生在中国最贫困地区的小孩笔下的诗,类似的还有《刮胡刀》、《时间里的刀》、《距离》等等,他们用仅学的最简单的词汇描绘生活。伟大的作品大多来自苦难,自己或是别人的苦难,诗歌也好,电影也罢,普通人的真相大约是工具人实锤了。回想我小时候写的东西早已经都丢掉,印象中模糊地记得义非将操场一角实心球比喻成扒满灰尘的乌龟,不知道为什么记了这么久,大约是我仍旧贫瘠。期待我们的国家彻底摆脱落后贫瘠,苟日新日日新又日新,科技工业的发展铺就成长的路,教育进步成为每个人心中的‘白昼流星’。” img “2020会被消灭的硬骨头 img ” 05 — 喜欢的照片 昆明的阳光占据了全年的大部,附带赠送强烈紫外线,好处是可以无脑拍出好看的天。 img img img img img img img “秋已尽,冬渐藏,望春玉兰芽三两。 千里遥,万般念,啼血杜鹃春风惘? 来年近,近咫尺,关心尤甚,盼红妆。 磐石蒲苇不改,杏黄枫红未逝,心亦常在。” 早晨出门的路上 06 — 微小的工作 Joint Framework for Image Fusion and Super-Resolution via Multicomponent Analysis and Residual Compensation 今年十一月末算是读研以来的一个分界线,一直以来担心的事情有了暂时的结尾,虽然兜兜转转还是在研究生灌水乐园添了一瓢,安慰自己聊胜于无。两年多的时间里,我大致知道普通人的科研是怎么一回事,大牛们的事迹了解了一些,我固然有兴趣做一点儿什么,但一个人成长,固然需要自身的努力更要看到历史的进程。读硕士的经历足以让我明白,不是我不读研读博,而是我没有那个能力与基础,至此,我更加佩服有勇气继续念下去的同学伙伴,带着一点儿羡慕。当然这不是说我不再自我更新,只是,我很可能与某种形式的学习说再见了,哪怕我曾经对它有过期许。二十多岁,心有戚戚焉,想做的事还多想学的还多,但愿我能继续折腾,达到某个健康的生活状态。 img END — 结语 如同万千工具人一样,自我奋斗能向上攀爬的距离从刚出生开始就已经决定,我能做的只有躺平。前面星星点点的内容皆是小米便签带来的,有的写在火车上,有的写在颓废的深夜,没有多少连贯性,我自己的心境也是,常常很丧偶尔正能量。我曾经用心安利其中一些给别人,但是你珍惜的在别人眼中可能只是垃圾,我也想自己有完美光辉的一面,显然我没法取悦所有人,日常傻一点儿,在朋友圈是积极阳光的,去微博吐槽,去知乎豆瓣装逼,去参与“朝天门抽烟走不走?”,去接受陌生人社交,去丧且正能量地活着。2020,会接着躺平么? img 参考 1. 图片来自豆瓣海报、书籍插图、互联网以及个人拍摄 2. 豆瓣2019年度电影榜单https://movie.douban.com/annual/2019?source=navigation 3. 豆瓣2018年度电影榜单https://movie.douban.com/annual/2018?source=broadcast","tags":[{"name":"2020元旦","slug":"2020元旦","permalink":"http://yoursite.com/tags/2020%E5%85%83%E6%97%A6/"}]},{"title":"AndrewNg Machine Learning 总结之Linear regression","date":"2020-01-09T13:51:38.262Z","path":"2020/01/09/AndrewNgMachineLearning总结之LinearRegression/","text":"Linear regression线性回归模型:$$h_\\theta(x)=\\theta^Tx$$ 代价函数:$$J(\\theta)={(1/2m)}{\\sum_{i=1}^{m}{(h_\\theta(x^{(i)})-y^{(i)})^2}}$$ 123456789101112function J = computeCost(X, y, theta)m = length(y);% number of training examples方法1: for i=1:m J=J+(X(i,:)*theta-y(i,:))^2/(2*m); end方法2:J=sum((X*theta-y).^2)/(2*m);%此处用.^2对每个值求平方,然后用sum()函数求和利用sunm()函数方法3:(通用于单变量、多变量回归)J=((X*theta-y)'*(X*theta-y))/(2*m);%向量相乘亦可得到同样的和值end 梯度下降法更新theta:$$\\theta_j:=\\theta_j-\\alpha(1/m){\\sum_{i=1}^{m}{(h_\\theta(x^{(i)})-y^{(i)}){x_j^{(i)}}}}$$ 12345678910111213141516171819function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)m = length(y); J_history = zeros(num_iters, 1);for iter = 1:num_iters% x=X(:,2);%得到列向量x1% theta0=theta(1);%得到初值,% theta1=theta(2);% theta0=theta0-(alpha/m)*sum((X*theta-y));%x0为全1的列向量,不必写出% theta1=theta1-(alpha/m)*sum((X*theta-y).*x);%使用点乘.*直接得到每组数据相乘结果% theta=[theta0;% theta1];%theta是size(2,1)的矩阵,定义时theta = zeros(2, 1)这里theta0与theta1之间应该用分号隔开,表示两行 theta = theta - alpha / m * X' * (X * theta - y);%整合上面对每个theta操作,写成矩阵形式 %为了绘制出J(theta)曲线 % Save the cost J in every iteration J_history(iter) = computeCost(X, y, theta);endend 正规方程法直接得到theta解析解:$$\\theta=(X^TX)^{-1}{X^T}y$$ 12345function [theta] = normalEqn(X, y)theta = zeros(size(X, 2), 1);% theta=((X'*X)^-1)*X'*y;theta = pinv(X' * X) * X' * y;end 特征归一化:$$x:=(x^i-mu)/s^i$$ 12345678910111213141516171819function [X_norm, mu, sigma] = featureNormalize(X)X_norm = X;mu = zeros(1, size(X, 2));sigma = zeros(1, size(X, 2)); m = length(X(:,1));%for i=1:size(X, 2)%mu(i)=sum(X(:,i))/m;%sigma(i)=std(X(:,i));%std(X(:,1)) computes the standard deviation%x=(X(:,i)-mu(i))./sigma(i);%X(:,i)-mu(i))表示每列的每个元素减去均值,./表示点除%X_norm(:,i)=x;%end mu=mean(X); sigma=std(X); for i = 1:size(X,2), X_norm(:,i) = (X(:,i) - mu(i)) / sigma(i); endend","tags":[{"name":"Linear regression","slug":"Linear-regression","permalink":"http://yoursite.com/tags/Linear-regression/"},{"name":"Matlab","slug":"Matlab","permalink":"http://yoursite.com/tags/Matlab/"}]},{"title":"CUDA+cuDNN+TF 安装流程和经验教训","date":"2020-01-09T13:51:38.262Z","path":"2020/01/09/CUDA+cuDNN+TF-安装流程和经验教训/","text":"摘要:Ubuntu18.04、GCC降低、CUDA版本的选择、cuDNN的选择前言:在经历一整天反复安装卸载后决定对每一步进行详细记录和分析 对版本选择的考虑我的目的是在Ubuntu18.04安装GPU版本的Tensorflow进行学习,根据TF官网对CUDA&cuDNN的支持信息: 软件要求必须在您的系统上安装以下NVIDIA®软件: NVIDIA®GPU 驱动程序 -CUDA 9.0需要384.x或更高版本。 CUDA®Toolkit- TensorFlow支持CUDA 9.0。 CUPTI附带CUDA工具包。 cuDNN SDK(> = 7.2) (可选) NCCL 2.2支持多GPU支持。 (可选) TensorRT 4.0 可以改善某些型号推理的延迟和吞吐量。 于是在考虑最新的TF版本情况下,我决定安装CUDA9.0+cuDNN7.3版本 cuda:https://developer.nvidia.com/cuda-90-download-archive?target_os=Linux&target_arch=x86_64&target_distro=Ubuntu&target_version=1704&target_type=runfilelocal cudnn:https://developer.nvidia.com/rdp/cudnn-download(需要先注册账户) 然而尴尬的是CUDA9.0没有ubuntu18.04的选择,不想重装ubuntu,于是我决定下载17.04版本试试看 最终下载版本:cuda_9.0.176_384.81_linux.run & cudnn-9.0-linux-x64-v7.3.1.20.tgz 安装CUDA1.安装依赖关系参考:https://www.cnblogs.com/Ph-one/p/9000211.html 1sudo apt-get install freeglut3-dev build-essential libx11-dev libxmu-dev libxi-dev libgl1-mesa-glx libglu1-mesa libglu1-mesa-dev 根据诸多博客的经验,还需要先降低GCC版本,以下是我的gcc版本信息: 12root@zhou-pc:~# gcc --versiongcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 降低GCC版本: 1sudo apt install gcc-5 g++-5 根据提示开始安装低版本 然后替换: 12sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 50 # you will find that message that tells you the gcc-5 is set to be automatic.sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 50 # similiar message as gcc 值得一提的是文章https://blog.csdn.net/sinat_40276791/article/details/80403784中提到说:**安装cuda的时候并没有降级gcc,g++;说明cuda9.0已经支持gcc7.0安装,所谓降级是后面要编译cuda测试例子的时候用到6.0以下的g++,和gcc版本。**但是我的gcc版本较高,为保险,我还是先降低。 2.开始安装CUDA12root@zhou-pc:~# cd /home/zongpu/下载 root@zhou-pc:/home/zongpu/下载# sudo sh cuda_9.0.176_384.81_linux.run ctrl+c 可快速结束阅读文档 接下来: Do you accept the previously read EULA?accept/decline/quit: accept 看到这个我是很荒的,但是博客https://www.cnblogs.com/Ph-one/p/9000211.html也是在ubuntu18.04上安装了cuda9,就当试试 You are attempting to install on an unsupported configuration. Do you wish to continue?(y)es/(n)o [ default is no ]: 其他选项我都选了y(es),静静等待安装。 设置环境变量: 1sudo gedit ~/.bashrc #在打开的文本中添加 12export PATH=/usr/local/cuda-9.0/bin:$PATHexport LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH 更新: 1source ~/.bashrc 验证CUDA9.0是否安装成功: 123cd /usr/local/cuda-9.0/samples/1_Utilities/deviceQuerysudo make./deviceQuery 输出为: 123456789101112131415161718192021222324252627282930313233343536373839CUDA Device Query (Runtime API) version (CUDART static linking)Detected 1 CUDA Capable device(s)Device 0: \"GeForce GTX 1050\" CUDA Driver Version / Runtime Version 9.1 / 9.0 CUDA Capability Major/Minor version number: 6.1 Total amount of global memory: 2003 MBytes (2099904512 bytes) ( 5) Multiprocessors, (128) CUDA Cores/MP: 640 CUDA Cores GPU Max Clock rate: 1493 MHz (1.49 GHz) Memory Clock rate: 3504 Mhz Memory Bus Width: 128-bit L2 Cache Size: 524288 bytes Maximum Texture Dimension Size (x,y,z) 1D=(131072), 2D=(131072, 65536), 3D=(16384, 16384, 16384) Maximum Layered 1D Texture Size, (num) layers 1D=(32768), 2048 layers Maximum Layered 2D Texture Size, (num) layers 2D=(32768, 32768), 2048 layers Total amount of constant memory: 65536 bytes Total amount of shared memory per block: 49152 bytes Total number of registers available per block: 65536 Warp size: 32 Maximum number of threads per multiprocessor: 2048 Maximum number of threads per block: 1024 Max dimension size of a thread block (x,y,z): (1024, 1024, 64) Max dimension size of a grid size (x,y,z): (2147483647, 65535, 65535) Maximum memory pitch: 2147483647 bytes Texture alignment: 512 bytes Concurrent copy and kernel execution: Yes with 2 copy engine(s) Run time limit on kernels: Yes Integrated GPU sharing Host Memory: No Support host page-locked memory mapping: Yes Alignment requirement for Surfaces: Yes Device has ECC support: Disabled Device supports Unified Addressing (UVA): Yes Supports Cooperative Kernel Launch: Yes Supports MultiDevice Co-op Kernel Launch: Yes Device PCI Domain ID / Bus ID / location ID: 0 / 1 / 0 Compute Mode: < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) >deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 9.1, CUDA Runtime Version = 9.0, NumDevs = 1Result = PASS 测试说明安装成功! 安装cuDNN之前已经下载好了文件现在直接安装: 123456tar -zxvf cudnn-9.0-linux-x64-v7.3.1.20.tgzsudo cp cuda/include/cudnn.h /usr/local/cuda/include/ sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64/ -d sudo chmod a+r /usr/local/cuda/include/cudnn.h sudo chmod a+r /usr/local/cuda/lib64/libcudnn* 执行以上命令后,测试是否安装好: 1nvcc -V 输出: 1234nvcc: NVIDIA (R) Cuda compiler driverCopyright (c) 2005-2017 NVIDIA CorporationBuilt on Fri_Sep__1_21:08:03_CDT_2017Cuda compilation tools, release 9.0, V9.0.176 cuDNN安装成功! 安装Tensorflow1检查并准备所需python环境根据TF官网安装引导查看:https://tensorflow.google.cn/install/pip 123python3 --versionpip3 --versionvirtualenv --version 发现: 12Command 'virtualenv' not found, but can be installed with:apt install virtualenv 我的virtualenv 没有安装,根据提示安装virtualenv : 1sudo apt install virtualenv 安装成功后,安装TF,在这里我用官网引导的安装方式:创建Python虚拟环境用于将程序包安装与系统隔离, 不同于在之前我自己直接pip install tensorflow-gpu 步骤如下: 通过选择Python解释器并创建一个./venv目录来保存它,从而创建一个新的虚拟环境 : 1virtualenv --system-site-packages -p python3 ./venv 如下: 123456root@zhou-pc:~# virtualenv --system-site-packages -p python3 ./venvRunning virtualenv with interpreter /usr/bin/python3Using base prefix '/usr'New python executable in /root/venv/bin/python3Not overwriting existing python script /root/venv/bin/python (you must use /root/venv/bin/python3)Installing setuptools, pip, wheel...done. 使用特定于shell的命令激活虚拟环境(以后每次使用TF前激活): 1source ./venv/bin/activate # sh, bash, ksh, or zsh 当virtualenv处于活动状态时,shell提示符前缀为(venv),如下: 12root@zhou-pc:~# source ./venv/bin/activate (venv) root@zhou-pc:~# 在虚拟环境中安装软件包,而不会影响主机系统设置。从升级开始pip: 123pip install --upgrade pippip list # show packages installed within the virtual environment 并在以后退出virtualenv(我们要在这个环境中安装TF,现在不能退出): 1deactivate #在使用TensorFlow完成之前不要退出 值得一提的是:当环境创建好了,我们必须在每次使用tensorflow时激活它 2.安装TensorFlow(在虚拟环境venv中)123pip install tensorflow-gpupip install --upgrade tensorflowpython -c \"import tensorflow as tf; print(tf.__version__)\" 最后输出: 12(venv) root@zhou-pc:~# python -c \"import tensorflow as tf; print(tf.__version__)\"1.11.0 greaat!现在我们安装TF成功! 一个问题:在虚拟环境中安装的始终是cpu版本,不知道为什么;不在虚拟环境中可顺利安装GPU版本。 3.做一些测试(在venv环境以及非虚拟环境)执行: 12345pythonimport tensorflow as tfhello = tf.constant('Hello, TensorFlow!')sess = tf.Session()print(sess.run(hello)) 非虚拟环境时可看到(展示部分): 1GeForce GTX 1050, pci bus id: 0000:01:00.0, compute capability: 6.1 虚拟环境中: 1I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA 安装keras参考:https://keras-cn.readthedocs.io/en/latest/for_beginners/keras_linux/ 类似指令比较多,我没有关注他们的区别: 123sudo pip install -U --pre keras#或者...pip install keras -U --pre 安装anaconda先下载anaconda的安装文件,我的版本是:Anaconda3-5.3.0-Linux-x86_64.sh cd进文件所在目录执行: 1bash Anaconda3-5.3.0-Linux-x86_64.sh 阅读文档(ctrl+c快速读完),按提示选择各个选项,进行安装: 其中涉及安装路径、添加环境变量、安装vs code的几个选项,根据提示选择。 但是安装时我选了环境变量后来还是不能启动anaconda,于是手动添加了一遍: 1234# 将anaconda的bin目录加入PATH,根据版本不同,也可能是~/anaconda3/binecho 'export PATH=\"~/anaconda3/bin:$PATH\"'>> ~/.bashrc# 更新bashrc以立即生效source ~/.bashrc 执行: 1conda list 看到各个组件信息则为成功 启动anaconda(暂停终端则断开): 1anaconda-navigator 打开 Jupyter Notebook: 1ipython notebook 在最开始安装anaconda时,我用root权限进行安装,结果Jupyter不能运行, 123456root@zhou-pc:/home/zongpu/下载# ipython notebook[TerminalIPythonApp] WARNING | Subcommand `ipython notebook` is deprecated and will be removed in future versions.[TerminalIPythonApp] WARNING | You likely want to use `jupyter notebook` in the future[I 18:30:46.711 NotebookApp] JupyterLab extension loaded from /root/anaconda3/lib/python3.7/site-packages/jupyterlab[I 18:30:46.711 NotebookApp] JupyterLab application directory is /root/anaconda3/share/jupyter/lab[C 18:30:46.713 NotebookApp] Running as root is not recommended. Use --allow-root to bypass. 这应该是我对anaconda的作用不太了解,另外都使用了默认安装路径,不知道在以后要用到的时候会不会出问题。 卸载anaconda: 1rm -rf ~/anaconda3 补充一篇基于anacond安装TF的文章: Ubuntu环境下基于Anaconda安装Tensorflowhttps://blog.csdn.net/hgdwdtt/article/details/78633232","tags":[{"name":"Tensorflow","slug":"Tensorflow","permalink":"http://yoursite.com/tags/Tensorflow/"}]},{"title":"有关Git&Hexo的一些小事儿","date":"2019-04-24T13:05:15.000Z","path":"2019/04/24/有关Git-Hexo的一些小事儿/","text":"这是一些平时所遇到小问题的记录 1.Hexo上传的图片在网页上无法显示的解决办法感觉问题的原因就是图片没有跟随.md文件一同上传Github,找不到图片路径,因而无法显示。 (1) 找到Hexo下的_config.yml里的post_asset_folder,把这个选项从false改成true; (2) 在Hexo目录下打开Git Brsh,执行一个下载上传图片插件的命令npm install hexo-asset-image --save; *(3) *继续在Git Brsh下利用hexo n "Hexo这是一个测试文件"来生成md的文件(” “里的内容填自己的文件名),这时就会在同级的目录下生成一个同名的文件夹; (4) 在.md的文件中要插入图片时,先要把所要插入的图片放在生成的同名文件夹下; (5) 利用markdown的语法将文件引入文章中; (6) 提交hexo clean –>hexo generate –>hexo deploy。 参考文献: 1.https://blog.csdn.net/qq_38148394/article/details/79997971 2.Hexo d 生成博客时出现warning: LF will be replaced by CRLF in ……的解决办法问题如下: 123warning: LF will be replaced by CRLF in 2019/04/24/Hexo-test/index.html.The file will have its original line endings in your working directory.warning: LF will be replaced by CRLF in about/index.html. 解决方法: 1git config --global core.autocrlf false 因就是(我并不懂): 原因是路径中存在 / 的符号转义问题,false就是不转换符号默认是true,相当于把路径的 / 符号进行转义,这样添加的时候就有问题 参考文献: https://blog.csdn.net/wxl1555/article/details/53033739","tags":[{"name":"Hexo","slug":"Hexo","permalink":"http://yoursite.com/tags/Hexo/"},{"name":"Git","slug":"Git","permalink":"http://yoursite.com/tags/Git/"}]}]