左神算法、牛客网算法-初级4(python实现)

转圈打印矩阵

【要求】 额外空间复杂度为O(1)。

def print_circle(arr,top_row,top_column,down_row,down_column):
    if top_row == down_row:
        for i in range(top_column, down_column + 1):
            print(arr[top_row][i], end=" ")
    elif top_column == down_column:
        for i in range(top_row, down_row + 1):
            print(arr[top_column][i], end=" ")
    else:
        for i in range(top_column, down_column):
            # 第一行打印  从第一列到最后一列
            print(arr[top_row][i], end=" ")
        for i in range(top_row, down_row):
            print(arr[i][down_column], end=" ")
        for i in range(down_column, top_column, -1):
            print(arr[down_row][i], end=" ")
        for i in range(down_row, top_row, -1):
            print(arr[i][top_column], end=" ")   
def get_print(arr):
    if not arr:
        return []
    m = len(arr) - 1
    n = len(arr[0]) - 1
    top_row = 0
    top_column = 0
    down_row = m
    down_column = n
    while down_row >= top_row and down_column >= top_column:
        print_circle(arr,top_row,top_column,down_row,down_column)
        top_row += 1
        top_column += 1
        down_row -= 1
        down_column -= 1

arr = [
    [1,2,3],
    [4,5,6],
    [7,8,9]
]
get_print(arr)

旋转正方形矩阵

【题目】 给定一个整型正方形矩阵matrix, 请把该矩阵调整成
顺时针旋转90度的样子。
【要求】 额外空间复杂度为O(1)。

def roation_square(arr):
    if not arr:
        return []
    m = len(arr) - 1
    n = len(arr[0]) - 1
    top_row = 0
    top_column = 0
    down_row = m
    down_column = n
    while down_row > top_row and down_column > top_column:
        for i in range(top_column,down_column):
            arr[i][down_column], arr[down_row][down_column - i],arr[down_row - i][top_column],arr[top_row][i] = arr[top_row][i],arr[i][down_column], arr[down_row][down_column - i],arr[down_row - i][top_column]
#             arr[top_row][i],arr[i][down_column], arr[down_row][down_column - i],arr[down_row - i][top_column] = a,b,c,d
        top_row += 1
        top_column += 1
        down_row -= 1
        down_column -= 1
arr = [
    [1,2,3,4],
    [5,6,7,8],
    [9,10,11,12],
    [13,14,15,16]
]
roation_square(arr)
arr
[[13, 9, 5, 1], [14, 6, 6, 2], [15, 7, 11, 3], [16, 12, 8, 4]]

“之” 字形打印矩阵

【题目】 给定一个矩阵matrix, 按照“之” 字形的方式打印这
个矩阵, 例如:
1 2 3 4
5 6 7 8
9 10 11 12

“之” 字形打印的结果为: 1, 2, 5, 9, 6, 3, 4, 7, 10, 11,8, 12
【要求】 额外空间复杂度为O(1)。

def printMatrix(arr):
    a_row = 0
    a_column = 0
    b_row = 0
    b_column = 0    
    count = False
    end_row = len(arr) - 1
    end_column = len(arr[0]) - 1
    while a_row <= end_row and a_column <= end_column:
        print_level(arr,a_row,a_column,b_row,b_column,count)
        if a_column == end_column:
            a_row += 1
        else:
            a_column += 1
        if b_row == end_row:
            b_column += 1
        else:
            b_row += 1
        count = not count

def print_level(arr,a_row,a_column,b_row,b_column,count):
    if not count:
        # 向上打印
        # 行数从大到小  列数从小到大
        j = b_column
        for i in range(b_row,a_row - 1, -1):
            print(arr[i][j], end=" ")
            j += 1
    else:
        j = a_column
        for i in range(a_row,b_row + 1):
            print(arr[i][j], end=" ")
            j -= 1
        

arr = [
    [1, 2, 3, 4],
    [5, 6, 7, 8], 
    [9, 10, 11, 12]
]
printMatrix(arr)
1 2 5 9 6 3 4 7 10 11 8 12 

在行列都排好序的矩阵中找数

【题目】 给定一个有N*M的整型矩阵matrix和一个整数K,
matrix的每一行和每一 列都是排好序的。 实现一个函数, 判断K
是否在matrix中。 例如: 0 1 2 5 2 3 4 7 4
4 4 8 5 7 7 9 如果K为7, 返回true; 如果K为6, 返
回false。
【要求】 时间复杂度为O(N+M), 额外空间复杂度为O(1)。

def get_bool(arr,num):
    n = len(arr) - 1
    m = len(arr[0]) - 1
    row = n
    column = 0
    while row >= 0 and column <= m:
        if arr[row][column] > num:
            row -= 1
        elif arr[row][column] < num:
            column += 1
        else:
            return True
    return False
    
arr = [
    [0,1,2,5],
    [2,3,4,7],
    [3,4,4,8],
    [4,7,7,9]
]
get_bool(arr,5)
True
not []
True

打印两个有序链表的公共部分

【题目】 给定两个有序链表的头指针head1和head2, 打印两个
链表的公共部分。

class Node():
    def __init__(self,val):
        self.val = val
        self.next = None
def get_same_node(head1,head2):
    cur1 = head1
    cur2 = head2
    while cur1 and cur2:
        if cur1.val == cur2.val:
            print(cur1.val)
        elif cur1.val >= cur2.val:
            cur2 = cur2.next
        else:
            cur1 = cur1.next

判断一个链表是否为回文结构

【题目】 给定一个链表的头节点head, 请判断该链表是否为回
文结构。 例如: 1->2->1, 返回true。 1->2->2->1, 返回true。
15->6->15, 返回true。 1->2->3, 返回false。
进阶: 如果链表长度为N, 时间复杂度达到O(N), 额外空间复杂
度达到O(1)。

def get_bool(head):
    # 用栈进行倒序,空间复杂度O(n)
    if not head:
        return True
    cur = head
    stack = []
    while cur:
        stack.append(cur)
        cur = cur.next
    cur = head
    while cur:
        if cur == stack.pop():
            cur = cur.next
        else:
            return False
    return True

用栈进行倒序,空间复杂度O(n)
或者找到中点,前半段压入栈中,再出栈和后半段进行比较,额外空间复杂度O(n/2)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ej4yOnDr-1588470102855)(attachment:image.png)]

按上图改变链表结构后,从两个头开始进行比对(奇数),额外空间复杂度O(1)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F3v7Y7oH-1588470102860)(attachment:image.png)]
指针指到null时 结束,最后数据结构还原

将单向链表按某值划分成左边小、 中间相等、 右边大的形式

【题目】 给定一个单向链表的头节点head, 节点的值类型是整型, 再给定一个
整 数pivot。 实现一个调整链表的函数, 将链表调整为左部分都是值小于 pivot
的节点, 中间部分都是值等于pivot的节点, 右部分都是值大于 pivot的节点。
除这个要求外, 对调整后的节点顺序没有更多的要求。 例如: 链表9->0->4->5-

1, pivot=3。 调整后链表可以是1->0->4->9->5, 也可以是0->1->9->5->4。 总
之, 满 足左部分都是小于3的节点, 中间部分都是等于3的节点(本例中这个部
分为空) , 右部分都是大于3的节点即可。 对某部分内部的节点顺序不做 要求。
进阶: 在原问题的要求之上再增加如下两个要求。
在左、 中、 右三个部分的内部也做顺序要求, 要求每部分里的节点从左 到右的
顺序与原链表中节点的先后次序一致。 例如: 链表9->0->4->5->1, pivot=3。
调整后的链表是0->1->9->4->5。 在满足原问题要求的同时, 左部分节点从左到
右为0、 1。 在原链表中也 是先出现0, 后出现1; 中间部分在本例中为空, 不再
讨论; 右部分节点 从左到右为9、 4、 5。 在原链表中也是先出现9, 然后出现4,
最后出现5。
如果链表长度为N, 时间复杂度请达到O(N), 额外空间复杂度请达到O(1)。

# 额外空间复杂度达到O(n)
def Nrther_land(head, num):
    arr = []
    cur = head
    while cur:
        arr.append(cur)
        cur = cur.next
    quick_sort(arr,num,0,len(arr)-1)
    for i in range(len(arr)-1):
        arr[i].next = arr[i+1]
    arr[-1].next = None

def quick_sort(arr,num,first,last):
    less = first - 1
    more = last - 1
    cur = first
    while cur < more:
        if arr[cur].val == num:
            cur += 1
        elif arr[cur].val < num:
            less += 1
            arr[less], arr[cur] = arr[cur], arr[less] 
            cur += 1
        elif arr[cur].val > num:
            more -= 1
            arr[more], arr[cur] = arr[cur], arr[more]       
def get_result(head,num):
    if not head:
        return False
    cur = head
    less_head = None
    equal_head = None
    more_head = None
    while cur:
        if cur.val == num:
            if not equal_head:
                equal_head = Node(num)
                equal = equal_head.next
            else:
                equal = Node(num)
                equal = equal.next
        if cur.val < num:
            if not less_head:
                less_head = Node(num)
                less = less_head.next
            else:
                less = Node(num)
                less = less.next
        if cur.val > num:
            if not more_head:
                more_head = Node(num)
                more = more_head.next
            else:
                more = Node(num)
                more = more.next
        cur = cur.next
    # 判断less more  equal  是否为空  最后拼接
        

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oQ042CJa-1588470102864)(attachment:image.png)]

第一次拿到less eq more 节点,再次遍历查找下一个这三种节点(less节点碰到一样的去下一个),最后拿到三个链表,再串在一起。
注意空节点

复制含有随机指针节点的链表

【题目】 一种特殊的链表节点类描述如下:
public class Node { public int value; public Node next; public
Node rand;
public Node(int data) { this.value = data; }
} N
ode类中的value是节点值, next指针和正常单链表中next指针的意义
一 样, 都指向下一个节点, rand指针是Node类中新增的指针, 这个指
针可 能指向链表中的任意一个节点, 也可能指向null。 给定一个由
Node节点类型组成的无环单链表的头节点head, 请实现一个 函数完成
这个链表中所有结构的复制, 并返回复制的新链表的头节点。 进阶:
不使用额外的数据结构, 只用有限几个变量, 且在时间复杂度为 O(N)
内完成原问题要实现的函数。
哈希表 python字典, dic = {old:clone}
dic[old].next = dic[old.next]
dic[old].random = dic[old.random]

"""
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random
"""

class Solution:
    def copyRandomList(self, head: 'Node') -> 'Node':
        if not head:
            return None
        cur = head
        dic = {}
        while cur:
            clone = Node(cur.val)
            dic[cur] = clone
            cur = cur.next
        for old in dic.keys():
            if old.next in dic:
                dic[old].next = dic[old.next]
            if old.random in dic:
                dic[old].random = dic[old.random]
        return dic[head]

不用哈希表最后再分离链表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2NLvaJh8-1588470102869)(attachment:image.png)]

"""
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random
"""

class Solution:
    def copyRandomList(self, head: 'Node') -> 'Node':
        if not head:
            return None
        cur = head
        while cur:
            # 复制链表 Node(cur.val)
            tmp = cur.next
            cur.next = Node(cur.val)
            cur.next.next = tmp
            cur = tmp
        cur = head
        while cur:
            tmp = cur.next
            if cur.random:
                tmp.random = cur.random.next
            cur = tmp.next
        new_head = head.next
        cur = head
        while cur:
            cur_next = cur.next.next
            cur_copy = cur.next
            cur.next = cur_next
            cur_copy.next = cur_next.next if cur_next else None
            cur = cur_next

        return new_head

两个单链表相交的一系列问题

【题目】 在本题中, 单链表可能有环, 也可能无环。 给定两个
单链表的头节点 head1和head2, 这两个链表可能相交, 也可能
不相交。 请实现一个函数, 如果两个链表相交, 请返回相交的
第一个节点; 如果不相交, 返回null 即可。 要求: 如果链表1
的长度为N, 链表2的长度为M, 时间复杂度请达到 O(N+M), 额外
空间复杂度请达到O(1)。

查看是否有环

使用哈希表visited,遍历链表,如果 node in visited,则有环,且node为如环结点
不使用哈希表,快指针和慢指针,快指针一次两步,慢指针一次一步,当相遇时,证明有环。此时将快指针重置到头节点,
快指针步数变为一步,当再次相遇时,为入环结点

# Definition for singly-linked list.
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        if not head:
            return False
        visited = set()
        cur = head
        while cur:
            if cur not in dic:
                visited.add(cur)
            else:
                return True
            cur = cur.next
        return False

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        if not head or not head.next or not head.next.next:
            return False
        slow = head.next
        fast = head.next.next
        while slow != fast:
            # 此处判断的应该是fast指针的下个和下下个
            if not fast.next or not fast.next.next:
                return False
            slow = slow.next
            fast = fast.next.next
        fast = head
        while slow != fast:
            slow = slow.next
            fast = fast.next
        return slow

查看是否相交:

(1)如果都无环,将head1的链表全部放入visited中,遍历head2链表,如果遇到相同的则相交
不用哈希表
记录两个链表的长度吗m,n,及end结点,查看两个结点的内存地址是否相同,如果相同,长的链表先走m-n步,再和
短链表一起走,碰到的第一个相同的结点(内存地址)即为相交的第一个结点
(2) 不肯能存在一个有环一个无环

(3) 两个都有环

head1 head2
loop1 loop2(end 结点的内存)

loop1 = loop2 情况2
loop1 != loop2
分情况1和3
遍历head1 看loop2是否出现,出现则相交,且为相交结点,否则不相交
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O3oJq780-1588470102873)(attachment:image.png)]

你可能感兴趣的:(数据结构与算法)