力扣刷題記錄(一)

 

今天開始正式刷題,爲找工做作準備,這篇博客用來記錄一下;刷題順序是先刷hot題目前100個node

1.兩數之和:python

比較簡單,一次就作出來。面試

思路:python的字典是哈希存儲的,看了一下dict內置方法只有has_key,因此將值做爲key,下標做爲value,存儲字典,而後遍歷列表,以當前值爲基準,用has_key判斷(target-當前值)是否存在,存在則返回相應的下標便可。,代碼以下:數據結構

class Solution(object): def twoSum(self, nums, target): """ :type nums: List[int] :type target: int :rtype: List[int] """ info={} # 將數據存入到字典當中 for i in range(len(nums)): info[nums[i]] = i for i in range(len(nums)): temp = target-nums[i] if info.has_key(temp): return [info[temp],i]

 2.兩數相加app

給了兩個鏈表,表明兩個數字,逆序存儲。將兩個數字相加,存儲成相同的鏈表格式,返回。ide

第一次沒作出來,看了答案纔會的,第二次作有一些小bug,認真分析以後對一些細節地方理解更深入了。函數

思路:不須要將兩個數算出來而後相加,只須要將每一位相加,加的過程當中判斷是否有進位,若是有進位的話就多加一個1。另外注意這塊沒有新建立節點,而是直接使用a,b已經存在的節點,更改他們的值,注意這裏是默認使用a節點,a爲空了則使用b節點。另外注意循環最後一句是在拼接目標鏈表,而這一句優化

p = (a==null?b:a);是在更改目標鏈表的值爲正確的值。

 

/**
 * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; *     ListNode(int x) { val = x; } * } */
class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode p = null; ListNode a = l1; ListNode b = l2; int carry=0;   //進位標誌 int val; //每一位的和 while(a!=null || b!=null){ val = (a==null?0:a.val) + (b==null?0:b.val) + carry;  //計算該位的值 carry = val>=10?1:0; val = val%10;  //必須是小於10的 p = (a==null?b:a);    //讓p指向當前a,b裏面不爲空的,默認是a p.val = val;  //更新節點的值 a = (a==null?null:a.next);  //後移節點 b = (b==null?null:b.next); p.next=(a==null?b:a);   //將p也後移一下,這一部無所謂,只是單純的後移一下, } //最後的進位判斷 if(carry>0){ p.next=new ListNode(1); } return l1; } }

 

 很久不寫了,一方面考試太多了,另外一方面也是本身太懶了,買了一本《劍指offer》,配合這個好好刷一下題,另外準備按照題目難度刷spa

1.合併二叉樹code

題目描述:將兩個二叉樹進行合併, 若是兩個樹的當前節點都不爲空,則將其值合併,不然取其中不爲空的節點,最後返回一個新的樹。

思路:雖然是一個比較簡單的題,可是數據結構都忘了好多,開始還想了半天。整體上直接使用原來的內存空間就能夠了, 這樣就不須要再去申請內存建立新的節點了。採用先序遍歷的方法遍歷這棵樹,當前節點若是有一個爲空的,則返回另外一個不空的,默認先判斷t1,若是兩個都不空的話就將值累加給t1的當前節點以後返回t1節點,都爲空的狀況已經包含在了第一種狀況。

對一種狀況的說明:由於咱們是採用拼接的方法獲得最終生成樹的,因此並非必需要遍歷完兩顆樹的全部節點,好比若是當前t1.left爲空,t2.left不爲空,則將t2.left賦給t1.lft,而且t2.left的全部子節點也都跑到了t1.left之下,因此以後就就不須要再遍歷t2.left的子節點了,由於t1.left沒有子樹,以後遍歷的取值確定都是t2的。

代碼比較簡單:
遞歸的方法:

class Solution { public TreeNode mergeTrees(TreeNode t1, TreeNode t2) { //先序遍歷兩顆樹,將和累加到A樹當中,若是其中一個空的話,則直接返回另一個不空的,而且能夠把那個不爲空的子節點直接擴展到其中去
        if(t1 == null){ return t2; } if(t2 == null){ return t1; } t1.val += t2.val;   //合併當前節點
        t1.left = mergeTrees(t1.left, t2.left);  //合併左子樹,一個爲空則不合並
        t1.right = mergeTrees(t1.right, t2.right);   //合併右子樹
        return t1; } }
View Code

面試時候若是你寫遞歸的話,面試官會問你優化方法,因此仍是老老實實的把非遞歸的也看一下:

非遞歸使用棧來完成,初始時候把兩個根節點做爲一項入棧,以後每一次從棧之中取出一個元素,判斷該元素之中的兩個節點爲null的狀況,

1.都爲null的話,則無需再對這兩個節點的子樹進行討論,跳過本次循環

2.若是有一個爲空或者兩個都不爲空, 則將值累加到t1節點當中,並對t1.left和t1.right進行考察,若是爲空的話,則直接將t2.left或者t2.right賦值給t1對應節點,若是不爲空,則將t1.left和t2.left做爲一項append到棧之中,以後進行考察。

代碼:   !!!!!!!這個非遞歸的代碼是錯誤的,以前沒有認真看,今天再次回顧時候才發現,錯誤代碼就放在這裏,以示警惕。

錯誤地方我不想,你們本身拿到leetcode上面運行一下,漏洞百出,以前太不仔細了,這個非遞歸代碼就是cv的,當時也沒注意是錯的。

class Solution: def mergeTrees(self, t1: TreeNode, t2: TreeNode) -> TreeNode: if not t1: return t2 stack = [[t1,t2]] while stack: t = stack.pop() if (not t[0]) and (not t[1]): continue t[0].val += t[1].val if not t[0].left: t[0].left = t[1].left else: stack.append([t[0].left,t[1].left]) if not t[0].right: t[0].right = t[1].right else: stack.append([t[0].right, t[1].right]) return t1
View Code

附上本身想的正確的代碼,用棧來轉換遞歸的先序遍歷,對於當前出棧元素有四種討論,(都爲空,(t[0非空,t[1]空)),(t[0]空,t[1]不空), (都不空),前兩種狀況作相同的處理,都是直接continue,第二種狀況須要將t[1]嫁接到t[0]處,第三種狀況相加節點,並添加新的元組到棧中。

代碼以下:

# Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def mergeTrees(self, t1: TreeNode, t2: TreeNode) -> TreeNode: if not t1: return t2 stack = [(t1,t2)] while stack: t = stack.pop() if (not t[0] and not t[1]) or (t[0] and not t[1]): continue elif t[0] and t[1]: t[0].val += t[1].val if not t[0].left: t[0].left = t[1].left else: stack.append((t[0].left,t[1].left)) if not t[0].right: t[0].right = t[1].right else: stack.append((t[0].right, t[1].right)) elif not t[0] and t[1]: t[0] = t[1] return t1 

 固然這個if,else的排列能夠深究一下,哈夫曼樹,這裏不說了。

2.兩個整數之間的漢明距離指的是這兩個數字對應二進制位不一樣的位置的數目。

給出兩個整數 x 和 y,計算它們之間的漢明距離。

題目思路:這個題比較簡單,就是比較二進制之中不相同的位的個數,要麼直接異或運算,而後計算1的個數,要麼先將他們轉換爲2進制以後計算不相同的位的個數,注意轉換時候必須讓他們總的位數相同,因此用or條件判斷

class Solution: def hammingDistance(self, x: int, y: int) -> int: """ 首先將兩個數字都轉換爲2進制數字存儲爲列表,以後找出來不同的項的個數 或者直接進行異或運算,計算結果裏面1的個數便可 """ res = [] num = 0 while x!=0 or y!=0: res.append((x%2, y%2)) x = x // 2 y = y // 2 for i in res: if i[0] != i[1]: num += 1 return num

可是這樣比較慢,能夠直接先異或,再統計1的個數

class Solution: def hammingDistance(self, x: int, y: int) -> int: """ 首先將兩個數字都轉換爲2進制數字存儲爲列表,以後找出來不同的項的個數 或者直接進行異或運算,計算結果裏面1的個數便可 """ return bin(x ^ y).count('1')

統計1的個數函數已經封裝好了,可是也能夠本身寫,比較簡單,判斷該二進制最後一位是否是1,而後右移一位,再判斷,再右移,直到二進制數爲0。

class Solution: def hammingDistance(self, x: int, y: int) -> int: """ 首先將兩個數字都轉換爲2進制數字存儲爲列表,以後找出來不同的項的個數 或者直接進行異或運算,計算結果裏面1的個數便可 """ z = x ^ y num = 0 while z!=0: if z & 1 == 1: num += 1 z = z >> 1 return num

後面兩種方法同樣快,第一種方法最慢,應該是運算次數比較多的緣故吧。

相關文章
相關標籤/搜索