剑指offer代码python3版

本文精选了22道经典算法题目,涵盖了数组查找、链表操作、二叉树构建、正则表达式匹配等多个方面,提供了详细的实现思路和代码示例,帮助读者深入理解算法原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 数组查找

题目描述: 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

class Solution:
    # array 二维列表
    def Find(self, target, array):
        # write code here
        for i in range(len(array)):
            if target in array[i]:
                return True
        return False
if __name__ == '__main__':
    s = Solution()
    array = [[2,3,4],[3,4,5]]
    print(s.Find(5,array))

2. 替换空格

题目描述: 请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy,则经过替换之后的字符串为We%20Are%20Happy。
实现方法: 先扫描一遍字符串,得出空格的个数,将新字符串的长度限制为原字符串的长度+2*空格个数,从尾到头转移原字符串,并将其中的空格替换为%20

class Solution:
    def replaceSpace(self, s):
        num_space = 0
        new_s = []
        for char in s:
            if char == ' ':
                num_space += 1
            new_s.append(char)
        new_s = new_s + ['='] * 2 * num_space
        s_i = len(s) - 1
        new_s_i = len(new_s) - 1
        while s_i >= 0 and s_i < new_s_i:
            if s[s_i] == ' ':
                new_s[new_s_i-2 : new_s_i+1] = ['%', '2', '0']
                new_s_i -= 3
            else:
                new_s[new_s_i] = s[s_i]
                new_s_i -=1
            s_i -= 1
        new_s = ''.join(new_s)
        return new_s
if __name__ == '__main__':
    s = ' wdad ed '
    solt = Solution()
    print(solt.replaceSpace(s))

3. 从尾到头打印链表

题目描述: 输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
实现方法: 1、递归实现     2、栈实现

# 从尾至头打印链表
class ListNode:
    def __init__(self, v):
        self.val = v
        self.next = None
    def create(self, p, v):
        while p.next != None:
            p = p.next
        p.next = ListNode(v)
# 递归实现
class recurSolution:
    def printListFromTailToHead(self, listNode):
        res = []
        def printListnode(listNode):
            if listNode:
                printListnode(listNode.next)  # 先递归到最后一层
                res.append(listNode.val)  # 添加值,退出函数,返回到上一层函数中的这行,继续添加值

        printListnode(listNode)
        return res
# 栈实现
class stackSolution:
    def printListFromTailToHead(self, listNode):
        chain = []
        res = []
        p = listNode
        while p != None:
            chain.append(p.val)
            p = p.next
        while len(chain) != 0:
            res.append(chain.pop())
        return res
if __name__ == '__main__':
    recur_s = recurSolution()
    stack_s = stackSolution()
    head = ListNode(1)
    head.create(head, 2)
    head.create(head, 3)
    print(recur_s.printListFromTailToHead(head))
    print(stack_s.printListFromTailToHead(head))

4. 根据先序和中序遍历重建二叉树

题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
实现方法: 先根据先序序列寻找根的位置,再去中序序列中找根的位置,确定完两个序列的根的位置后,将两个序列中的值各自分为3类,左子树下的所有节点、根、右子树下的所有节点,再分别将左子树、右子树内的值按上述方法递归分类。递归结束条件:子树部分只有一个节点,即子树为叶子节点。

# 给定前序和中序遍历,重建二叉树
class treeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre, tin):
        def ConstructCore(startPre, endPre, startIn, endIn):
            rootVal = pre[startPre]
            root = treeNode(rootVal)
            if startPre == endPre:
                if startIn == endIn and pre[startPre] == tin[startIn]:
                    return root
                else:
                    print('Invalid input.')
            # 在中序遍历中找到根节点
            rootIn = startIn
            while rootIn < endIn and tin[rootIn] != rootVal:
                rootIn += 1
            if rootIn == endIn and tin[rootIn] != rootVal:
                print('Invalid input.')
            leftLength = rootIn - startIn
            leftPreEnd = startPre + leftLength
            if leftLength > 0: # 若左子树不为空,构建左子树
                root.left = ConstructCore(startPre+1, leftPreEnd, startIn, rootIn-1)
            if leftLength < endIn - startIn: # 若右子树不为空,则构建右子树
                root.right = ConstructCore(leftPreEnd+1, endPre, rootIn+1, endIn)
            return root
        assert len(pre) == len(tin)
        if pre == None or tin == None or len(pre) == 0:
            return None
        else:
            return ConstructCore(0, len(pre)-1, 0, len(tin)-1)
if __name__ == '__main__':
    s = Solution()
    pre = [1,2,3,4,5,6,7]
    tin = [3,2,4,1,6,5,7]
    print(s.reConstructBinaryTree(pre, tin).val)

5. 二叉树的下一个节点

题目描述: 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
实现方法: 分为4种情况:1、树只有一个节点或None节点,直接返回None. 2、给定节点有右子树,那么下一个节点为其右子树的最左叶子。3、给定节点无右子树,且为其父节点的左孩子,直接返回其父节点。4、给定节点无右子树,且为其父节点的右孩子,需要一直找其父节点,直到找到某个节点为其父节点的左孩子,或找到了根结点(父节点为None),则返回该父节点。

class TreeLinkNode:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None
        self.next = None
class Solution():
    def GetNext(self, node):
        p_next = None
        if node.right != None:
            p = node.right
            while p.left != None:
                p = p.left
            p_next = p
        elif node.next != None:
            p_c = node
            p_parent = node.next
            while p_parent != None and p_c == p_parent.right:
                p_c = p_parent
                p_parent = p_parent.next
            p_next = p_parent
        return p_next

6. 用两个栈实现队列

题目描述: 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
实现方法: push时,直接将新元素入栈进stack1。pop时,若stack2为空则将stack1的所有元素依次入栈stack2,并出栈stack2的栈顶元素,若转移后stack2仍为空,则说明队列为空,无法出队;若stack2不为空,只需出栈stack2中的栈顶元素即可。

# 利用两个栈实现队列
class Solution:
    def __init__(self):
        self.stack1 = []
        self.stack2 = []
    def push(self, node):
        self.stack1.append(node)
    def pop(self):
        if len(self.stack2) == 0:
            while len(self.stack1) > 0:
                self.stack2.append(self.stack1.pop())
        if len(self.stack2) == 0:
            print('queue is empty!')
        else:
            return self.stack2.pop()
if __name__ == '__main__':
    s = Solution()
    s.push(1)
    s.push(2)
    s.push(3)
    s.pop()
    s.pop()
    s.pop()

相关题目: 利用两个队列实现入栈出栈函数。

from queue import Queue
class Solution2:
    def __init__(self):
        self.q1 = Queue(maxsize=0)
        self.q2 = Queue(maxsize=0)
    def push(self, node):
        if not self.q1.empty():
            self.q1.put(node)
        elif not self.q2.empty():
            self.q2.put(node)
        else:
            self.q1.put(node)
    def pop(self):
        if not self.q1.empty():
            while self.q1.qsize() > 1:
                self.q2.put(self.q1.get())
            return self.q1.get()
        elif not self.q2.empty():
            while self.q2.qsize() > 1:
                self.q1.put(self.q2.get())
            return self.q2.get()
        else:
            print('stack empty')

7. 斐波那契数列

题目描述: 现在要求输入一个整数n,请你输出斐波那契数列的第n项
实现方法: 循环 or 递归。

# 斐波那契数列
class Solution:
    def Fibonacci_1(self, n):   # 循环实现
        fnm1 = 1
        fnm2 = 0
        if n == 0:
            return fnm2
        elif n == 1:
            return fnm1
        else:
            for i in range(2, n+1):
                f = fnm1 + fnm2
                fnm2 = fnm1
                fnm1 = f
            return f
    def Fibonacci_2(self, N):   # 递归实现,超时
        def FibonacciRe(n):
            if n == 0:
                return 0
            elif n == 1:
                return 1
            else:
                return FibonacciRe(n-1) + FibonacciRe(n-2)
        return FibonacciRe(N)
if __name__ == '__main__':
    s = Solution()
    print(s.Fibonacci_1(39))

8. 青蛙跳台阶

题目描述: 青蛙跳台阶,若一共有n级台阶,一次可以跳1级台阶,或一次可以跳2级台阶。
实现方法: f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n)=f(n-1)+f(n-2) f(n)=f(n1)+f(n2)

9. 变态跳台阶

题目描述: 若青蛙一次可以跳1级or一次可以跳2级,or……or一次可以跳n级。
实现方法: f ( n ) = 2 n − 1 f(n)=2^{n-1} f(n)=2n1

10. 矩阵覆盖

题目描述: 我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
实现方法: f ( n ) = f ( n − 1 ) + f ( n − 2 ) f(n)=f(n-1)+f(n-2) f(n)=f(n1)+f(n2)
8、10均为斐波那契数列思想

11. 旋转数组

题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
实现方法: 二分法,目标是找到两个递增数组的边界。使用双指针,index1指向首元素,index2指向尾元素,找中间位置的元素值,若大于index1的元素,则目标一定在indexMid之后;若小于index2的元素,则目标一定在indexMid之前,若index1和index2和indexMid位置的值都相等,则只能顺序查找。

public class Main11 {
    public int minNumberInRotateArray(int [] array) {
        int p1 = 0;
        int p2 = array.length-1;
        int mid = 0;
        while (array[p1] >= array[p2]) {
            mid = (p2+p1) / 2;
            if (array[p1] == array[mid] && array[mid] == array[p2]) {
                return inOrder(array);
            }
            if (array[p1] <= array[mid]) {
                p1 = mid;
            }
            else if (array[p2] >= array[mid]) {
                p2 = mid;
            }
            if (p2-p1 == 1) {
                mid = p2;
                break;
            }
        }
        return array[mid];
    }
    public int inOrder(int[] array) {
        int min = array[0];
        for (int i = 1; i < array.length ; i++) {
            if (array[i] < min){
                min = array[i];
            }
        }
        return min;
    }
    public static void main(String[] args) {
        Main11 m = new Main11();
        int[] array = {10,1,10,10,10};
        System.out.println(m.minNumberInRotateArray(array));
    }
}

12. 矩阵中的路径

题目描述: 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如
[ a b c e s f c s a d e e ] \left[ \begin{matrix} a & b & c & e \\ s & f & c & s \\ a & d & e & e \end{matrix} \right] asabfdcceese
矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
实现方法: 递归回溯法,需要额外的访问数组visited,重点在20行代码

public class Main12 {
    public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
        int[] visited = new int [rows * cols];
        int pathLen = 0;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if(hasPathCore(matrix, rows, cols, i, j, visited, pathLen, str)) {
                    return true;
                }
            }
        }
        return false;
    }
    public boolean hasPathCore(char[] matrix, int rows, int cols, int row, int col, int[] visited, int pathLen, char[] str) {
        if (pathLen == str.length) {
            return true;
        }
        boolean hasC = false;
        if (row>=0 && row<rows && col>=0 && col<cols && visited[row * cols + col]==0 && matrix[row * cols + col]==str[pathLen]) {
            visited[row * cols + col] = 1;
            pathLen++;
            hasC = hasPathCore(matrix, rows, cols, row-1, col, visited, pathLen, str) ||
                   hasPathCore(matrix, rows, cols, row+1, col, visited, pathLen, str) ||
                   hasPathCore(matrix, rows, cols, row, col-1, visited, pathLen, str) ||
                   hasPathCore(matrix, rows, cols, row, col+1, visited, pathLen, str);
            if (!hasC) {
                visited[row * cols + col] = 0;
                pathLen--;
            }
        }
        return hasC;
    }
    public static void main(String[] args) {
        Main12 m = new Main12();
        char[] matrix = {'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'};
        char[] str = {'A','A','A','A','A','A','A','A','A','A','A','A'};
        System.out.println(m.hasPath(matrix, 3, 4, str));
    }
}

13. 机器人的运动范围

题目描述: 地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
实现方法: 递归回溯法,重点在13行代码

public class Main13 {
    public int movingCount(int threshold, int rows, int cols) {
        int[][] visited = new int[rows][cols];
        return countCore(threshold, rows, cols, 0, 0, visited);
    }
    public int countCore(int threshold, int rows, int cols, int row, int col, int[][] visited) {
        int count = 0;
        if (row>=0 && row<rows && col>=0 && col<cols && visited[row][col]==0 && weiSum(row,col)<=threshold) {
            visited[row][col] = 1;
            count = 1 + countCore(threshold, rows, cols, row-1, col, visited)
                      + countCore(threshold, rows, cols, row+1, col, visited)
                      + countCore(threshold, rows, cols, row, col-1, visited)
                      + countCore(threshold, rows, cols, row, col+1, visited);
        }
        return count;
    }
    public int weiSum(int x, int y) {
        int sum = 0;
        while (x > 0) {
            sum += x % 10;
            x = x / 10;
        }
        while (y > 0) {
            sum += y % 10;
            y = y / 10;
        }
        return sum;
    }
    public static void main(String[] args) {
        Main13 m = new Main13();
        System.out.println(m.movingCount(3, 3, 3));
    }
}

14. 剪绳子

题目描述: 给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],…,k[m]。请问k[0]xk[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
实现方法: 1、时间复杂度为 O ( n 2 ) O(n^2) O(n2),空间复杂度为 O ( n ) O(n) O(n)的动态规划。2、时间复杂度和空间复杂度都为 O ( 1 ) O(1) O(1)的贪心算法。

import java.util.ArrayList;
public class Main14 {
    public int cuttingRope(int n) {
        if (n == 2)
            return 1;
        if (n == 3)
            return 2;
        ArrayList<Integer> array = new ArrayList();
        array.add(0);
        array.add(1);
        array.add(2);
        array.add(3);
        int max = 0;
        for (int i = 4; i <= n; i++) {
            for (int j = 1; j <= i/2; j++) {
                if (array.get(j) * array.get(i-j) > max) {
                    max = array.get(j) * array.get(i-j);
                }
            }
            array.add(max);
        }
        return max;
    }
    public int tanxin(int n) {
        if (n == 2)
            return 1;
        if (n == 3)
            return 2;
        int numOf3 = n / 3;
        if (n - numOf3 * 3 == 1)
            numOf3--;
        int numOf2 = (n - numOf3 * 3) / 2;
        return (int)(Math.pow(3, numOf3) * Math.pow(2, numOf2));
    }
    public static void main(String[] args) {
        Main14 m = new Main14();
        System.out.println(m.tanxin(10));
    }
}

15. 二进制中1的个数

题目描述: 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
实现方法: 1、 c = 1 c = 1 c=1, 让原数 & c \&c &c,并不断将 c c c左移一位,直到 c c c大于 2 31 − 1 2^{31}-1 2311        2、任何一个二进制数 & \& &(自己-1)都会讲该二进制数的最右边的1变为0,检查变了多少次该数才为0即可。

class Solution:
    def NumberOf1_1(self, n):
        x = 1
        count = 0
        while x < 2**32:
            if n & x:
                count += 1
            x = x << 1
        return count
    def NumberOf1_2(self, n):
        count = 0
        while n >= -2**31 and n != 0:
            count += 1
            n = n & (n - 1)
        return count
if __name__ == '__main__':
    s = Solution()
    print(s.NumberOf1_2(-1))

16. 数值的整数次方

题目描述: 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。保证base和exponent不同时为0
实现方法: 注意指数为负数、底数为0的情况。
在这里插入图片描述

import sys
class Solution:
    def Power(self, base, exponent):
        if base == 0 and exponent < 0:
            raise Exception('Invalid input!')
        if base == 0:
            return 0
        newExponent = abs(exponent)
        res = self.powerCore(base, newExponent)
        if exponent < 0:
            res = 1 / res
        return res
    def powerCore(self, base, exponent):
        if exponent == 0:
            return 1
        if exponent == 1:
            return base
        res = self.powerCore(base, exponent >> 1)
        res *= res
        if exponent & 0x1 == 1:
            res *= base
        return res
if __name__ == '__main__':
    s = Solution()
    line = sys.stdin.readline().strip()
    num = list(map(int, line.split()))
    print(s.Power(num[0], num[1]))

17. 打印从1到最大的n位数

python不用考虑大数越界问题

import sys
class Solution:
    def printNumbers(self, n):
        tar = 10 ** n - 1
        for i in range(1, tar+1):
            print(i)
if __name__ == '__main__':
    s = Solution()
    n = int(sys.stdin.readline().strip())
    s.printNumbers(n)

18.1 删除链表的节点

题目描述: 给定头节点和需要删除的节点,使用时间复杂度为 O ( 1 ) O(1) O(1)的算法实现删除该节点的操作。
实现方法: 将下一个节点的值复制到该删除的节点,再删除下一个节点,若需要删除的节点为尾节点,则必须从头遍历,找到倒数第二个节点,再进行删除。

class ListNode:
    def __init__(self, val):
        self.val = val
        self.next = None
    def createNode(self, nodeP, val):
        curNode = ListNode(val)
        while nodeP.next != None:
            nodeP = nodeP.next
        nodeP.next = curNode
class Solution:
    def deleteNode(self, nodeP, nodeN):
        if nodeN.next == None:
            p = nodeP
            while p.next != nodeN:
                p = p.next
            p.next = None
            del nodeN
            return nodeP
        elif nodeP.next == None:
            return None
        else:
            nodeN.val = nodeN.next.val
            nodeN.next = nodeN.next.next
            return nodeP
if __name__ == '__main__':
    s = Solution()
    nodeHead = ListNode(1)
    nodeHead.createNode(nodeHead, 2)
    nodeHead.createNode(nodeHead, 3)
    nodeHead.createNode(nodeHead, 4)
    nodeP = s.deleteNode(nodeHead, nodeHead)

18.2 删除链表中重复的节点

题目描述: 给定头节点,删除链表中所有重复的节点,包括其本身如:
原链表:1 -> 2 -> 2 -> 3 -> 4
删除后的链表:1 -> 3 -> 4

class ListNode:
    def __init__(self, val):
        self.val = val
        self.next = None
    def createNode(self, nodeP, val):
        curNode = ListNode(val)
        while nodeP.next != None:
            nodeP = nodeP.next
        nodeP.next = curNode
class Solution:
    def deleteSameNode(self, head):
        if head == None or head.next == None:
            return head
        preNode = None
        pNode = head
        while pNode:
            pNext = pNode.next
            needDelete = False
            if pNext and pNode.val == pNext.val:
                needDelete = True
            if not needDelete:
                preNode = pNode
                pNode = pNext
            else:
                toBeDeleted = pNode
                value = pNode.val
                while toBeDeleted and toBeDeleted.val == value:
                    pNode = toBeDeleted.next
                    del toBeDeleted
                    toBeDeleted = pNode
                if preNode == None:
                    head = pNode
                else:
                    preNode.next = pNode
        return head
if __name__ == '__main__':
    s = Solution()
    nodeHead = ListNode(1)
    nodeHead.createNode(nodeHead, 2)
    nodeHead.createNode(nodeHead, 3)
    nodeHead.createNode(nodeHead, 3)
    nodeHead = s.deleteSameNode(nodeHead)

19. 正则表达式匹配

题目描述: 请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’‘表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配
实现方法:
当模式中的第二个字符是 ∗ * 时:1、如果字符串第一个字符跟模式第一个字符匹配,可以有3种匹配方式:(1)模式后移2字符,相当于 x ∗ x* x被忽略;(2)字符串后移1字符,模式后移2字符,相当于 x ∗ x* x匹配一位;(3)字符串后移1字符,模式不变,即继续匹配字符下一位,相当于 x ∗ x* x匹配多位;2、如果字符串第一个字符跟模式第一个字符不匹配,则模式后移2个字符,继续匹配。
当模式中的第二个字符不是 ∗ * 时:1、如果字符串第一个字符和模式中的第一个字符相匹配,那么字符串和模式都后移一个字符,然后匹配剩余的部分。2、如果字符串第一个字符和模式中的第一个字符相不匹配,直接返回False。注意:切片超出范围即为空字符串,如a=‘a’,则a[1:]=’’,并不会报错

import sys
class Solution:
    def match(self, mystr, pattern):
        if mystr is None or pattern is None:
            return False
        return self.matchCore(mystr, pattern)
    def matchCore(self, mystr, pattern):
        if len(mystr) == 0 and len(pattern) == 0:
            return True
        if len(mystr) > 0 and len(pattern) == 0:
            return False
        if len(pattern) > 1 and pattern[1] == '*':
            if mystr and (pattern[0] == mystr[0] or pattern[0] == '.' ):
                return self.matchCore(mystr[1:], pattern[2:]) \
                       or self.matchCore(mystr[1:], pattern) \
                       or self.matchCore(mystr, pattern[2:])
            else:
                return self.matchCore(mystr, pattern[2:])
        if mystr and (pattern[0] == mystr[0] or pattern[0] == '.'):
            return self.matchCore(mystr[1:], pattern[1:])
        return False
if __name__ == '__main__':
    s = Solution()
    mystr = sys.stdin.readline().strip()
    pattern = sys.stdin.readline().strip()
    print(s.match(mystr, pattern))

20. 表示数值的字符串

题目描述: 请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。
实现方法: 设置3个bool型变量,分别代表已经遇到“.”、“e”或“E”、“数字”。1、当前字符为“+”或“-”时:如果当前不在字符串首部,并且没有遇到“e”或“E”,则返回False。2、当前字符为“.”时,如果已经遇到“.”或“e”或“E”都返回False。3、当前字符为“e”或“E”时,如果没有遇到过数字或已经遇到过“e”或“E”,则返回False,详见代码:

import sys
class Solution:
    def isNumeric(self, s):
        if s is None or s == '':
            return False
        s = s.strip()
        met_dot = met_e = met_digit = False
        for i, ch in enumerate(s):
            if ch in ['+', '-']:
                if i > 0 and (s[i-1] not in ['e', 'E']):
                    return False
            elif ch == '.':
                if met_dot or met_e:
                    return False
                met_dot = True
            elif ch in ['e', 'E']:
                if met_e or (not met_digit):
                    return False
                met_e = True
                met_digit = False
            elif ch.isdigit():
                met_digit = True
            else:
                return False
        return met_digit
if __name__ == '__main__':
    line = sys.stdin.readline().strip()
    s = Solution()
    print(s.isNumeric(line))

21. 调整数组顺序使奇数位于偶数前面

题目描述: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
实现方法: 设2个相邻指针i、j,j = i + 1,i遇到偶数时停止,j遇到奇数时停止,然后之间的数字后移。

# 调整数组顺序使奇数位于偶数前面
import sys
class Solution:
    def reOrderArray(self, array):  # 相邻双指针牛客网可通过
        if array == [] or len(array) == 1:
            return array
        i = 0
        j = 0
        while i < len(array) and j < len(array):
            while i < len(array) and array[i] & 1 != 0: # 若为奇数
                i += 1
            j = i + 1
            while j < len(array) and array[j] & 1 == 0: # 若为偶数
                j += 1
            if j < len(array):
                tmp_index = j
                tmp = array[j]
                while j > i:
                    array[j] = array[j-1]
                    j -= 1
                array[i] = tmp
                j = tmp_index
        return array
    # def reOrderArray(self, array): # 头尾双指针法不稳定,但时间复杂度低Leetcode上该方法可以
    #     if array == []:
    #         return []
    #     begin = 0
    #     end = len(array) - 1
    #     while begin < end:
    #         while array[begin] & 0x1 != 0 and begin < end:
    #             begin += 1
    #         while array[end] & 0x1 == 0 and end > begin:
    #             end -= 1
    #         if begin < end:
    #             tmp = array[begin]
    #             array[begin] = array[end]
    #             array[end] = tmp
    #             begin += 1
    #             end -= 1
    #     return array
if __name__ == '__main__':
    s = Solution()
    line = sys.stdin.readline().strip()
    array = list(map(int, line.split()))
    print(s.reOrderArray(array))

22. 链表的倒数第k个节点

题目描述: 输入一个链表,输出该链表中倒数第k个结点。
实现方法: 设2个指针,第一个从head往后走k-1步,第二个就在head,随后两个指针分别向前各走一步,直到第一个指针走到了尾节点。第二个节点即为倒数第k个节点。注意判断k大于链表长度的情况。

class ListNode:
    def __init__(self, val):
        self.val = val
        self.next = None
    def creatNode(self, head, val):
        p = head
        while not p.next is None:
           p = p.next
        p.next = ListNode(val)
class Solution:
    def FindKthToTail(self, head, k):
        if head is None or k <= 0:
            return None
        p_i = head
        count = 0
        while p_i and count < k-1 :
            p_i = p_i.next
            count += 1
        if p_i is None:
            return None
        p_j = head
        while p_i.next:
            p_i = p_i.next
            p_j = p_j.next
        return p_j
if __name__ == '__main__':
    s = Solution()
    head = ListNode(1)
    head.creatNode(head, 2)
    head.creatNode(head, 3)
    print(s.FindKthToTail(head, 4))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值