【前端部分】青训营题目的思维拓展:解题思路分享

840 阅读6分钟

前端笔试题目-编程题解

前言

近日无事,写题有感,遂作此文
本文所涉及的的题目来自于青训营前端笔试练习(编程)题,题目的题解基于我的个人实践,很多东西基于我个人的理解,所以有望大家多多指教。
为了照顾更多读者,我使用了PythonGolang两种语言分别编写了题目的题解。考虑到前端题目的受众问题,我会在文末的码上掘金更新JavaScript版本题解。如果你发现了本文的错误之处,欢迎你在评论区留言,我会及时的进行修改。如果你有其他的想法,也欢迎在评论区留言,我会在看到评论的第一时间回复。
Tips为了更好地整合文章,我已经将本文章收录至专栏“青训营题解”,专栏内有其他方向的内容,感兴趣的小伙伴可以关注一下专栏。

题目:4的幂

给定一个十进制整数字符串,判断它是否是 4 的幂。

示例 1
输入:"16",

输出:true
示例 2
输入:"101",

输出:false
示例 3
输入:"70368744177664",

输出:true

题解

写题思路

本题可以使用递归或者循环来解决

递归:一般而言,如果一个函数在内部调用自己,那么这个函数就可以被称为递归函数。递归函数在执行时会产生一系列的函数调用,直到满足某个条件才会停止。

循环:循环是一段在程序中只出现一次,但可能会连续执行多次的代码。循环允许程序重复执行一段代码。循环会在满足某个条件时停止执行。

递归和循环的区别在于,递归函数在执行过程中会产生一系列的函数调用,而循环则不会。递归函数也可能会消耗更多的内存空间,因为它需要记录所有的函数调用。循环可能更加高效,因为它可以在执行过程中避免产生大量的函数调用。

对于本题而言,如果一个整数n是4的幂,那么他一定存在整数x满足4nx4n \cdot x

具体可以看看代码实现(本题使用递归实现,小伙伴们如果感兴趣可以在评论区贴出循环的代码)

代码实现

Python解法

def is_power_of_four(s):
    # 因为 4 的 0 次幂是 1,所以判断值是否为 1
    if s == '1':
        return True
    # 字符串表示的数不是 4 的幂
    if int(s) % 4 != 0:
        return False
    # 递归调用
    return is_power_of_four(str(int(s) // 4))

Golang解法

func isPowerOfFour(s string) bool {
   // 基本情况:字符串为空
   if s == "1" {
      return true
   }
   // 将字符串转换为整数
   n, err := strconv.Atoi(s)
   if err != nil {
      return false
   }
   // 基本情况:字符串表示的数不是 4 的幂
   if n%4 != 0 {
      return false
   }
   // 递归调用
   return isPowerOfFour(strconv.Itoa(n / 4))
}

结果展示

image.png

image.png

题目:验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略空格、字母的大小写。

示例

输入:"A man, a plan, a canal: Panama"

输出:true

题解

写题思路

本题可以使用双指针来解决

双指针(Two Pointers) :指的是在遍历元素的过程中,不是使用单个指针进行访问,而是使用两个指针进行访问,从而达到相应的目的。如果两个指针方向相反,则称为「对撞指针」。如果两个指针方向相同,则称为「快慢指针」。如果两个指针分别属于不同的数组 / 链表,则称为「分离双指针」。
关于双指针的知识可以参考此链接:01.数组双指针知识 | 算法通关手册 (itcharge.cn)

回文串是指正着读和反着读都是一样的字符串,要验证字符串,可以采用以下思路:

  1. 首先遍历字符串,删除字符串中的非字符部分,将剩余的字符都转化为小写。
  2. 使用双指针,从两端同时开始遍历字符串。如果两个指针指向的字符相同,则继续遍历;如果不同,则该字符串不是回文串。

具体可以看看代码实现

代码实现

Python解法

def is_palindrome(s):
    s = "".join(c.lower() for c in s if c.isalnum())
    i, j = 0, len(s) - 1
    while i < j:
        if s[i] != s[j]:
            return False
        i += 1
        j -= 1
    return True

Golang解法

func isPalindrome(s string) bool {
   s = strings.ToLower(s)
   s = strings.Map(func(r rune) rune {
      if r >= 'a' && r <= 'z' || r >= '0' && r <= '9' {
         return r
      }
      return -1
   }, s)
   i, j := 0, len(s)-1
   for i < j {
      if s[i] != s[j] {
         return false
      }
      i++
      j--
   }
   return true
}

结果展示

image.png

image.png

题目:最长回文子串的长度

给定一个字符串,找出该字符串中最长回文子串的长度。

示例 1

输入:"abc",

输出:0

示例 2

输入:"abcbe",

输出:3

示例 3

输入:"acdcecdcf",

输出:7

题解

写题思路

本题可以使用动态规划来解决

动态规划(Dynamic Programming,简称 DP)是一种用于解决最优化问题的算法设计技术,它的基本思想是将原问题分解为若干个子问题,然后通过记录这些子问题的解来解决原问题。

动态规划的分类:

  • 根据解决问题的方式,动态规划可以分为递归式 DP迭代式 DP
    • 递归式 DP 使用递归的方式来解决问题,而迭代式 DP 使用循环的方式来解决问题。(递归和循环的介绍可以看看第一题的写题思路)
  • 根据状态转移方程的形式,动态规划可以分为有界 DP 和无界 DP
    • 有界 DP:有界 DP 指的是状态转移方程中的状态是有界的,即状态的数量是有限的。例如,斐波那契数列的求解就是一个典型的有界 DP 问题。
    • 无界 DP:无界 DP 指的是状态转移方程中的状态是无界的,即状态的数量是无限的。例如,最长上升子序列的求解就是一个典型的无界 DP 问题。

同时,动态规划也有很多种形式,一维动规二维动规是其常见形式:

一维动规指的是状态转移方程中只有一个状态变量,例如斐波那契数列的求解,通常可以使用以下模型求解:

f[n] = f[n-1] + f[n-2]

一维动规的代码实现通常需要使用一个数组来存储中间结果,然后按照状态的顺序逐个转移

二维动规指的是状态转移方程中有两个状态变量,例如最长公共子序列的求解。二维动规的通用模型如下:

f[i][j] = max(f[i-1][j], f[i][j-1])

二维动规的代码实现通常需要使用一个二维数组来存储中间结果,然后按照状态的顺序逐个转移。

总之,一维动规和二维动规是动态规划的常见形式,在解决问题时需要根据具体情况来选择合适的形式。

具体可以看看代码实现(本体使用二维数组求解)

代码实现

def longestPalindromicSubstring(s):
    n = len(s)
    if n <= 0:
        return 0
    dp = [[False for _ in range(n)] for _ in range(n)]
    for i in range(n):
        for j in range(i, n):
            dp[i][j] = False
    for i in range(n):
        dp[i][i] = True
    max_length = 1
    for i in range(n - 1, -1, -1):
        for j in range(i, n):
            if s[i] == s[j]:
                if j - 1 >= i + 1:
                    if dp[i + 1][j - 1]:
                        dp[i][j] = True
                else:
                    dp[i][j] = True

            if dp[i][j]:
                length = j - i + 1
                if length > max_length:
                    max_length = length
    return max_length
package main

import "fmt"

func main() {
   fmt.Println(longestPalindromicSubstring("acdcecdcf"))
}

func longestPalindromicSubstring(s string) int {
   n := len(s)

   if n <= 0 {
      return 0
   }
   dp := make([][]bool, n)
   for i := 0; i < n; i++ {
      dp[i] = make([]bool, n)
   }
   for i := 0; i < n; i++ {
      for j := i; j < n; j++ {
         dp[i][j] = false
      }
   }
   for i := 0; i < n; i++ {
      dp[i][i] = true
   }
   maxLength := 1
   for i := n - 1; i >= 0; i-- {
      for j := i; j < n; j++ {
         if s[i] == s[j] {
            if j-1 >= i+1 {
               if dp[i+1][j-1] {
                  dp[i][j] = true
               }
            } else {
               dp[i][j] = true
            }
         }

         if dp[i][j] {
            length := j - i + 1
            if length > maxLength {
               maxLength = length
            }
         }
      }
   }
   return maxLength
}

结果展示

image.png

image.png

最后

如果你觉得本文对你有帮助,欢迎你留下一个大大的赞,你的支持是我更新最大的动力,下次更新会更快! (请点击Script查看代码)