算法练习题 - 回文字符串

18 篇文章 0 订阅

意图

使用单向链表实现判断一个字符串是否是回文字符串

思路

  1. 使用快、慢指针找出字符串中间那个数
  2. 找出前半部分字符串
  3. 遍历前半部分,和整个字符串挨个比较字符,如果都相等,则是回文字符串,反之不是

开发环境

  • swift4.2
  • Xcode11.3

示例代码

Node类
class Node<T>: NSObject, NSCopying {
    var next: Node?
    var data: T?
    override init() { }
    init(data: T?) {
        self.data = data
    }
    // 实现NSCopying协议方法
    func copy(with zone: NSZone? = nil) -> Any {
        var node: Node<T>? = self
        var copy: Node<T>?
        while node != nil {
            let tmp: Node<T>? = Node()
            tmp?.data = node?.data
            if node?.next != nil {
                tmp?.next = Node(data: node?.next?.data)
            }
            setNext(&copy, next: tmp)
            node = node?.next?.next
        }
        return copy as Any
    }
    // 设置子节点
    private func setNext(_ source: inout Node<T>?, next: Node<T>?) {
        if source == nil {
            source = next
            return
        }
        if source?.next == nil {
            source?.next = next
            return
        }
        var sourceNext = source?.next
        setNext(&sourceNext, next: next)
    }
    // 格式化打印对象
    override var description: String {
        var result = ""
        var node: Node<T>? = self
        
        while node != nil {
            if let data = node?.data {
                result += "\(data),"
                node = node?.next
            }
        }
        if result.count > 0 {
            // 删除最后一个逗号
            result.removeLast()
        }
        return result
    }
}
判断是否是回文字符串
func isPalindrome(_ str: Node<String>) -> Bool {
    // TIPS: 这里需要拷贝,否则在第二步操作的时候,会对源节点做修改
    var fast = str.copy() as? Node<String>
    var slow = str.copy() as? Node<String>
    // 1.找出回文中间那个数
    // 循环结束,fast指针指向最后一个元素,slow指针指向中间那个元素
    while fast?.next != nil && fast?.next?.next != nil {
        fast = fast?.next?.next
        slow = slow?.next
    }
    var current = slow?.next
    // 2.找出前半部分
    var pre: Node<String>?  // 回文前半部分
    while current != nil {
        let next = current?.next
        current?.next = pre
        pre = current
        current = next
    }
    // 遍历前半部分,和整个字符串挨个比较字符,如果都相等,则是回文字符串,反之不是
    var n1: Node<String>? = pre
    var n2: Node<String>? = str
    while pre != nil {
        if !(pre?.data == n2?.data) {
            return false
        }
        n1 = n1?.next
        n2 = n2?.next
    }
    return true
}
调用
/// 生成单链表
// 奇数回文
private func oddPalindrome() -> Node<String> {
    let node = Node(data: "1")
    node.next = Node(data: "2")
    node.next?.next = Node(data: "3")
    node.next?.next?.next = Node(data: "2")
    node.next?.next?.next?.next = Node(data: "1")
    return node
}
// 偶数回文
private func oddPalindrome() -> Node<String> {
    let node = Node(data: "1")
    node.next = Node(data: "2")
    node.next?.next = Node(data: "3")
    node.next?.next?.next = Node(data: "3")
    node.next?.next?.next?.next = Node(data: "2")
    node.next?.next?.next?.next?.next = Node(data: "1")
    return node
}
// 不是回文
private func errorPalindrome() -> Node<String> {
    let node = Node(data: "1")
    node.next = Node(data: "2")
    node.next?.next = Node(data: "3")
    node.next?.next?.next = Node(data: "2")
    return node
}
override func viewDidLoad() {
    super.viewDidLoad()
    let oddNode = oddPalindrome()
    let evenNode = evenPalindrome()
    let errorNode = errorPalindrome()
    println("\(oddNode) \(isPalindrome(oddNode) ? "是" : "不是")回文字符串")
    println("\(evenNode) \(isPalindrome(evenNode) ? "是" : "不是")回文字符串")
    println("\(errorNode) \(isPalindrome(errorNode) ? "是" : "不是")回文字符串")
}

在这里插入图片描述

思考

使用双向链表如何实现?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值