欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

左神算法-初级4(python)

程序员文章站 2022-07-02 22:35:01
这里写目录标题矩阵1、转圈打印矩阵2、旋转正方形矩阵3、“之” 字形打印矩阵链表1、判断一个单链表是否是回文结构2、链表与荷兰国旗问题3、复制含有随机指针节点的链表4、两个单链表相交问题矩阵1、转圈打印矩阵2、旋转正方形矩阵3、“之” 字形打印矩阵链表1、判断一个单链表是否是回文结构2、链表与荷兰国旗问题3、复制含有随机指针节点的链表4、两个单链表相交问题1、转圈打印矩阵【要求】 额外空间复杂度为O(1)转圈打印的过程就是不断顺时针打印外围元素的过程,只要给你一个左上角的点(如(0...

矩阵

1、转圈打印矩阵

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

转圈打印的过程就是不断顺时针打印外围元素的过程,
只要给你一个左上角的点(如(0,0))和右下角的点(如(3,3)),
你就能够打印出1 2 3 4 8 12 16 15 14 13 9 5;同样,给你(1,1)和(2,2),你就能打印出6 7 11 10。
这个根据两点打印正方形上元素的过程可以抽取出来,整个问题也就迎刃而解了。

def print_matrix(arr):
    if not arr:
        return []
    
    def print_circle(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=" ")   
    
    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(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]
]
print_matrix(arr)

2、旋转正方形矩阵

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

首先选取矩阵四个角上的点1,3,9,7,按顺时针的方向1到3的位置(1->3)、3->9、9->7、7->1,
这样对于旋转后的矩阵而言,这四个点已经调整好了。接下来只需调整2,6,8,4的位置,调整方法是一样的。
只需对矩阵第一行的前n-1个点采用同样的方法进行调整、对矩阵第二行的前前n-3个点……,
那么调整n阶矩阵就容易了。

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]
        top_row += 1
        top_column += 1
        down_row -= 1
        down_column -= 1
    return arr
        
arr = [
    [1,2,3,4],
    [5,6,7,8],
    [9,10,11,12],
    [13,14,15,16]]

print(roation_square(arr))

3、“之” 字形打印矩阵

【题目】 给定一个矩阵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 print_z_matrix(arr):
    a_row = 0
    a_column = 0
    b_row = 0
    b_column = 0
    end_row = len(arr) - 1
    end_column = len(arr[0]) - 1
    
    def print_level(a_row, a_column, b_row, b_column, flag):
        if flag == 0:
            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
        
    while a_row <= end_row:
        flag = 0
        print_level(a_row, a_column, b_row, b_column, flag)
        if a_column == end_column:
            a_row += 1
        else:
            a_column += 1
        if b_row == end_row:
            b_column += 1
        else:
            b_row += 1
        flag = not flag
        
arr = [
    [1, 2, 3, 4],
    [5, 6, 7, 8], 
    [9, 10, 11, 12]]

print_z_matrix(arr)

链表

1、判断一个单链表是否是回文结构

额外空间复杂度O(1)解法
常规思路,很容易想到准备一个。这样栈结构,把链表数据依次存入。
然后再同时遍历这两个链表,判断两个链表的当前节点是否相等(equal)。
这种解法实现很简单,时间复杂度为 O(n),额外空间复杂度为 O(n)。

使用快慢指针找到中间节点,把后半部分变成逆序链表

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

2、链表与荷兰国旗问题

将单向链表按某值划分成左边小、 中间相等、 右边大的形式
给定一个单向链表的头节点head, 节点的值类型是整型, 再给定一个
整 数pivot。 实现一个调整链表的函数, 将链表调整为左部分都是值小于 pivot
的节点, 中间部分都是值等于pivot的节点, 右部分都是值大于 pivot的节点。
除这个要求外, 对调整后的节点顺序没有更多的要求。

分别存入三个链表,small,equal,large中,三个链表分别标注头尾两个指针。

def partitionList(head, pivot):
    if not head:
        return False
    small_head = small_end = None
    mid_head = mid_end = None
    big_head = big_end = None
    p = head
    while p:
        if p.val < pivot:
            if not small_head:
                small_head = small_end =  p
            else:
                small_end.next = p
                small_end = p
        elif p.val == pivot:
            if not mid_head:
                mid_head = mid_end =  p
            else:
                mid_end.next = p
                mid_end = p
        else:
            if not big_head:
                big_head = big_end =  p
            else:
                big_end.next = p
                big_end = p
        p = p.next
    
    if small_head != None and mid_head != None and big_head != None:
        head = small_head
        small_end.next = mid_head
        mid_head.next = big_head
        big_end.next = None
    elif small_head != None and mid_head != None and big_head == None:
        head = small_head
        small_end.next = mid_head
        mid_head.next = None
    elif small_head != None and mid_head == None and big_head == None:
        head = small_head
        small_end.next = None
    elif small_head != None and mid_head == None and big_head != None:
        head = small_head
        small_end.next = big_head
        big_end.next = None
    
    elif small_head == None and mid_head != None and big_head != None:
        head = mid_head
        mid_end.next = big_head
        big_end.next = None
    elif small_head == None and mid_head != None and big_head == None:
        head = mid_head
        mid_head.next = None
    
    elif small_head == None and mid_head == None and big_head != None:
        head = big_head
        big_end.next = None
    return head

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

class Solution:
    # 返回 RandomListNode
    def Clone(self, pHead):
        # write code here
        if not pHead:
            return None
#         cur = pHead
#         dic = {}
#         while cur:
#             clone = RandomListNode(cur.label)
#             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[pHead]
        cur = pHead
        while cur:
            clone = RandomListNode(cur.label)
            clone.next = cur.next
            cur.next = clone
            cur = clone.next
        cur = pHead
        while cur:
            clone = cur.next
            if cur.random:
                clone.random = cur.random.next
            cur = clone.next
        cur = pHead
        head = pHead.next
        while cur and cur.next:
            clone = cur.next
            cur.next = clone.next
            cur = clone
        return head

4、两个单链表相交问题

两个单链表相交问题:三种情况如下:
1、两个无环单链表第一个交点
2、一个无环,一个有环单链表,不会相交
3、两个有环单链表第一个交点

解题思路:
首先判断两个链表是否有环;
如果都无环:两个无环单链表相交问题
如果一个有,一个无:必定不相交,直接返回 None
如果都有环:两个有环单链表相交问题

# 查看是否有环
#使用哈希表visited,遍历链表,如果 node in visited,则有环,且node为如环结点
def hascycle(head):
    if not head:
        return False
    seen = set()
    cur = head
    while cur:
        if cur in seen:
            return True
        seen.add(cur)
        cur = cur.next
    return False
# 快指针和慢指针,快指针一次两步,慢指针一次一步,当相遇时,证明有环。此时将快指针重置到头节点,
# 快指针步数变为一步,当再次相遇时,为入环结点
def hascycle2(head):
    if not head:
        return False
    p = head
    slow = p
    fast = p
    while fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            p1 = head
            while slow != p1:
                slow = slow.next
                p1 = p1.next
            return slow
    return None

# 查看是否相交:
def Intersect(head1, head2):
    loop1 = hascycle2(head1)
    loop2 = hascycle2(head2)
    
    def noloop(head1, head2):
        p1 = head1
        p2 = head2
        while p1 != p2:
            p1 = p1.next if p1 else head2
            p2 = p2.next if p2 else head1
        return p1
    def bothloop(head1, head2, loop1, loop2):
        p1 = head1
        p2 = head2
        # 入环结点相同,相交点不在环上
        # 先找到较长的一支,然后减去两支之差,此时长度相同,一起移动
        if loop1 == loop2:
            n = 0
            while p1.next != loop1:
                p1 = p1.next
                n += 1
            while p2.next != loop1:
                p2 = p2.next
                n -= 1
            if n>0:
                p1 = head1
                p2 = head2
            else:
                p1 = head2
                p2 = head1
            n = abs(n)
            while n != 0:
                p1 = p1.next
                n -= 1
            while p1 != p2:
                p1 = p1.next
                p2 = p2.next
            return p1
            
        else:
        # 入环结点不同,相交点在环上
        # 在链表1的环上转一圈,如果没有找到链表2的入环结点,说明不想交
            cur1 = loop1.next
            while cur1 != loop1:
                if cur1 == loop2:
                    return 1oop1  # 返回loop1或loop2均可,整个环就是两链表的相交部分
                cur1 = cur1.next
            return None
        
    
    if not loop1 and not loop2:
        return noloop(head1, head2)
    if loop1 and loop2:
        return bothloop(head1, head2)
    return None

本文地址:https://blog.csdn.net/weixin_43915860/article/details/110875567