【问题标题】:Where is my logic error in this recursive longest palindrome finder?在这个递归最长回文查找器中,我的逻辑错误在哪里?
【发布时间】:2020-01-03 13:38:37
【问题描述】:

我的目标是返回字节数组中最长的回文。我的算法是:

  • 分支 A

    • 从第一个字符到最后一个字符,字符串是回文吗?如果是,请退回。
    • 如果不是,从第一个字符到倒数第二个字符,字符串是回文吗? ...
    • 如果不是,从第一个字符到倒数第三个字符,字符串是回文吗? ...
    • ..
    • 是否还剩不到 2 个字符?如果是,请转到分支 A,但不要从第一个字符读取,而是从第二个字符开始检查。
    • ..
    • 是否还剩不到 2 个字符?如果是,请转到分支 A,但不要从第一个字符读取,而是从第三个字符开始检查。
    • ..
    • 是否还剩不到 2 个字符?返回`无。

这个问题本质上是迭代的,但算法似乎不适用于我的迭代或递归解决方案。 到目前为止,我已经做到了:

// slices are upper-bound exclusive
// return expressions are optionally implicit

fn is_palindrome(bytes: &[u8]) -> bool {
    if bytes.len() == 1 {
        true
    } else if bytes.len() == 2 {
        bytes[0] == bytes[1]
    } else if bytes[0] == bytes[bytes.len() - 1] {
        is_palindrome(&bytes[1..bytes.len() - 1])
    } else {
        false
    }
}

fn recurse_palindrome<'a>(s: &'a [u8], start: usize, end: usize) -> Option<&'a [u8]> {
    if start == end {
        if start == s.len() {
            None
        } else {
            // if start < s.len() - 1
            recurse_palindrome(&s, start + 1, s.len() - 1)
        }
    } else if is_palindrome(&s[start..end + 1]) {
        Some(&s[start..end + 1])
    } else {
        recurse_palindrome(&s, start, end - 1)
    }
}

pub fn longest_palindrome<'a>(s: &'a [u8]) -> Option<&'a [u8]> {
    recurse_palindrome(&s, 0, s.len() - 1)
}

// expected answers and tests
#[cfg(test)]
mod test {
    #[test]
    fn is_palindrome() {
        assert_eq!(super::is_palindrome(b"saas"), true); // ok
        assert_eq!(super::is_palindrome(b"ss"), true); // ok
    }

    #[test]
    fn longest_palindrome1() {
        assert_eq!(
            super::longest_palindrome(b"saasdbc").unwrap_or(b""),
            b"saas"
        ); // passes
    }

    #[test]
    fn longest_palindrome() {
        assert_eq!(
            super::longest_palindrome(b"ssaasdbc").unwrap_or(b""),
            b"saas"
        ); // fails; returns b"ss" instead of b"saas"
    }
}

【问题讨论】:

标签: algorithm recursion rust palindrome


【解决方案1】:

这个算法不起作用,因为它从左边找到第一个回文而不是最长的回文。

【讨论】:

    【解决方案2】:

    我会使用slice::windows 来迭代长度等于或小于原始切片的所有子切片。然后我找到第一个子切片是回文。我还重写了is_palindrome 进行迭代:

    fn is_palindrome(mut bytes: &[u8]) -> bool {
        loop {
            match bytes {
                [] | [_] => return true,
                other => {
                    let (h, m) = other.split_first().unwrap();
                    let (t, m) = m.split_last().unwrap();
                    if h != t {
                        return false;
                    }
                    bytes = m;
                }
            }
        }
    }
    
    pub fn longest_palindrome(s: &[u8]) -> Option<&[u8]> {
        (0..s.len())
            .rev()
            .flat_map(|l| s.windows(l + 1))
            .filter(|ss| is_palindrome(ss))
            .next()
    }
    

    当高级切片模式稳定后,is_palindrome 函数可以简化:

    #![feature(slice_patterns)]
    
    fn is_palindrome(mut bytes: &[u8]) -> bool {
        loop {
            match bytes {
                [] | [_] => return true,
                [h, m @ .., t] => {
                    if h != t {
                        return false;
                    }
                    bytes = m;
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-03-15
      • 1970-01-01
      • 1970-01-01
      • 2018-10-09
      • 2015-08-01
      • 2017-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多