数组

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,
使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,
并保证奇数和奇数,偶数和偶数之间的相对位置不变。

表面上这是一个很简单的任务,实际上应该夜不难…

但是有意义的事,如何仅在原有的数组之上来进行操作,而不是另外再开放一个空间.

举一个例子.

假设该数组为1,4,5,2,4,5,2

该如何进行操作呢?

我们概念中的交换数组元素的过程应该是这样的.

从第二个元素开始直到最后一个元素为止,如果这个元素为奇数,而前面的数为偶数,那么将这个数和前面的数交换.

这样的过程会将原来的那个数组依次变为

  • 1,5,4,2,4,5,2
  • 1,5,4,2,5,4,2

目前为止,显然没有完全完成任务.

但如果不断这样做,显然是可以成功的,但时间复杂度未免有点高了.

实际上,不难想到,如果放开相邻元素之间的交换,而改为直接插入会更好…

但是这样做又相当于改变了数组的数据结构.

暂时不大理解…

链表元素交换

举个例子说,我要反转一个链表,并且返回反转后的链表的头结点.

a->b->c->d->e

如何反转呢.

首先我们要明白一个事实,就是子节点不知道父节点是谁,所以一定有个变量保存着父节点的引用.

比如要将d->e反转为d<-e,只需让e指向d即可.

然而关键是d又怎么指向c呢?

看起来是个很难理解的问题…那就抽象吧…

我们假设上面的链表为L,有个过程X可以将L反转并且得到其头结点.

接下来就是如何拆解X的过程.

我们尝试这样做,将X分为:

  • X1: 用X将L的子节点所连接的链表反转,并且得到其头结点.
  • X2: 尾节点指向L的头结点.

看起来这是可行的,再自己看看对于基本情况,也就是输入L为0,1个节点的情况.

0的话返回空,1的话返回该节点

上面的想法是错误的,不应该从后往前推,而应该从前往后推

直接参照别人的代码吧.

class Solution:
    # 返回ListNode
    def ReverseList(self, pHead):
        if not pHead or not pHead.next:
            return pHead
        
        last = None
        while pHead:
            tmp = pHead.next
            pHead = last
            last = pHead
            pHead = tmp

        return last

指针

上面两个例子,跟指针都有关…

你对指针的了解很浅显…

现在仔细梳理一下.

先以链表为例,代码如下

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2018-06-12 11:23:21
# @Author  : yudanqu (943775910@qq.com)
# @Link    : https://www.cnblogs.com/yudanqu/
# @Version : $Id$


class Node(object):
    """节点"""

    def __init__(self, elem):
        self.elem = elem
        self.next = None  # 初始设置下一节点为空

'''
上面定义了一个节点的类,当然也可以直接使用python的一些结构。比如通过元组(elem, None)
'''


# 下面创建单链表,并实现其应有的功能


class SingleLinkList(object):
    """单链表"""

    def __init__(self, node=None):  # 使用一个默认参数,在传入头结点时则接收,在没有传入时,就默认头结点为空
        self.__head = node

    def is_empty(self):
        '''链表是否为空'''
        return self.__head == None

    def length(self):
        '''链表长度'''
        # cur游标,用来移动遍历节点
        cur = self.__head
        # count记录数量
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        '''遍历整个列表'''
        cur = self.__head
        while cur != None:
            print(cur.elem, end=' ')
            cur = cur.next
        print("\n")

    def add(self, item):
        '''链表头部添加元素'''
        node = Node(item)
        node.next = self.__head
        self.__head = node

    def append(self, item):
        '''链表尾部添加元素'''
        node = Node(item)
        # 由于特殊情况当链表为空时没有next,所以在前面要做个判断
        if self.is_empty():
            self.__head = node
        else:
            cur = self.__head
            while cur.next != None:
                cur = cur.next
            cur.next = node

    def insert(self, pos, item):
        '''指定位置添加元素'''
        if pos <= 0:
                # 如果pos位置在0或者以前,那么都当做头插法来做
            self.add(item)
        elif pos > self.length() - 1:
            # 如果pos位置比原链表长,那么都当做尾插法来做
            self.append(item)
        else:
            per = self.__head
            count = 0
            while count < pos - 1:
                count += 1
                per = per.next
            # 当循环退出后,pre指向pos-1位置
            node = Node(item)
            node.next = per.next
            per.next = node

    def remove(self, item):
        '''删除节点'''
        cur = self.__head
        pre = None
        while cur != None:
            if cur.elem == item:
                # 先判断该节点是否是头结点
                if cur == self.__head:
                    self.__head = cur.next
                else:
                    pre.next = cur.next
                break
            else:
                pre = cur
                cur = cur.next

    def search(self, item):
        '''查找节点是否存在'''
        cur = self.__head
        while not cur:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        return False


我很好奇