一个算法题的python和lisp实现和比较。

K个一组翻转链表的算法实现与面试应用 链表操作是数据结构与算法中的核心基础,其中翻转操作更是考察指针运用的经典场景。通过虚拟头节点双指针技术,可以实现高效的链表局部翻转。K个一组翻转链表问题结合了迭代与递归思想,在算法面试中出现频率极高,尤其考察工程师对边界条件的处理能力。这类问题在内存管理、数据分片等实际工程场景中也有应用价值。掌握链表翻转的迭代递归两种解法,不仅能提升算法能力,更能深入理解指针操作的精髓。 阅读详情

最近看到一个算法题:

给定一个 array,array中数字不重复,求出里面最长的连续的一段,它由连续的数组成,顺序任意

一看到题目就知道需要使用分治法,把数组分成左右两段,分别递归,但最长的有可能出现在中间,对中间的处理稍微复杂一点,但题目假设数组中的数字不重复,所以还是比较容易处理的。求出左中右三段的最长后,取他们的最大长度即可。

我分别用python和lisp解决该问题,其实是先写python,然后翻译成lisp。第一次使用lisp编程,不动手不知道,一动手发现有很多棘手的事情,经常编译不过,lisp的错误提示对初学者来说又比较晦涩,碰了不少钉子。吃一堑长一智,这就是动手的好处吧!

common lisp的开发体验和python很像,common lisp的交互式开发环境很棒,python学习和借鉴了 lisp很多的东西。

废话少说了,还是让代码说话吧,在我看来,这段lisp的代码和python的代码同样优雅,这是我始料未及的。性能没有比较,留给感兴趣的朋友吧!

lisp的实现:

(defparameter *mid_max_seq* nil)
(defun get_max_seq (li)
  "给定一个 array,array中数字不重复,求出里面最长的连续的一段,它由连续的数组成,顺序任意"
   (progn 
     (when (or (= 0 (length li)) (= 1 (length li))) 
         (return-from get_max_seq li))
     (let ((half (round (/ (length li) 2))))
       (format t "get_max_seq>>>>>>>>>li:~a, half:~d~%" li half)
       (get_max_mid_seq li (1- half) (1+ half))
       (setf left (get_max_seq (subseq li 0 half)))
       (setf right (get_max_seq (subseq li half)))
       (nth 0 (sort (list *mid_max_seq* left right) (lambda (x y) (> (length x) (length y)))))))) 

(defun is_seq (li)
  "判断li是否由连续数字组成,假设li无重复数字, 如果最大数-最小数=li长度-1,则为连续"
  (if (eql li nil)
    nil
    (=  (- (apply #'max li) (apply #'min li))  (- (length li) 1))))

(defun get_extend_limit (li left right)
  "将li从left和right向两侧扩展,直到将left和right之间不连续的数字都找到为止,并返回新的left和right"
    (let* ((min_value (apply #'min (subseq li left right)))
          (max_value (apply #'max (subseq li left right)))
          (miss_numbers (set-difference (range min_value max_value) (subseq li left right)))
          (new_left left)
          (new_right right))
          (format t "min:~d, max:~d, miss:~a~%" min_value max_value miss_numbers)
          (when (eql miss_numbers nil) 
            (error "miss_numbers should not be nil"))
          (when (> left right)
            (error "left should not larger than right"))
          
          (loop for value in (subseq li 0 left) do 
            (when (member value miss_numbers) 
              (setf new_left (position value li))
              (return)))
          (loop for value in (subseq li right) do 
            (when (member value miss_numbers) 
              (setf new_right (1+ (position value li)))))
          (when (> new_left new_right)
            (error "get_extend_limit return error: new_left>new_right"))
          (list new_left new_right)
          ))

(defun range (low up)
  (loop for i from low to up collect i))

(defun get_max_mid_seq (li left right )
  "从中间向两端搜索,可以优化"
  (progn 
    (format t "get_max_mid_seq>>>>>>>>li:~a, left:~d, right:~d~%" li left right)
  (if (is_seq (subseq li left right))
    (progn
        (when (> (length (subseq li left right)) (length *mid_max_seq*))
          (setf *mid_max_seq* (subseq li left right))
          (format t "update *mid_max_seq* to:~a~%" *mid_max_seq*))
        (when (> left 0)
          (get_max_mid_seq li (1- left) right ))
        (when (< right (length li))
          (get_max_mid_seq li left (1+ right) ))
        )
    (progn 
        (let ((new_left_right (get_extend_limit li left right)))
        (unless (and (= (first new_left_right) left) (= (second new_left_right) right))
          (get_max_mid_seq li (first new_left_right) (second new_left_right) )))))))
 

(defun test ()
  (progn 
    (test_get_max_mid_seq '(4 3 2 1 5 6) 2 4 '(4 3 2 1 5 6))
    (test_get_max_mid_seq '(4 3 2 1 9 8 7 6 5) 3 5 '(4 3 2 1 9 8 7 6 5))
    (test_get_max_mid_seq '(4 6 2 5 9 8 3 7 1) 3 5 '(4 6 2 5 9 8 3 7 1))

    (test_get_max_seq '(4 3 2 1 5 6) '(4 3 2 1 5 6))
    (test_get_max_seq '(4 3 2 1 7 6) '(4 3 2 1 ))
    (test_get_max_seq '(7 6 2 1 3 4) '(2 1 3 4 ))
    (test_get_max_seq '(7 4 2 1 3 6) '(4 2 1 3 ))
    (test_get_max_seq '(4 3 2 1 9 8 7 6 5) '(4 3 2 1 9 8 7 6 5))
    (test_get_max_seq '(4 6 2 5 9 8 3 7 1) '(4 6 2 5 9 8 3 7 1))
    ))

(defun test_get_max_seq(li expect)
  (progn
    (setf *mid_max_seq* nil)
    (assert (equal (get_max_seq li) expect))))

(defun test_get_max_mid_seq(li left right expect)
  (progn
    (setf *mid_max_seq* nil)
    (get_max_mid_seq li left right)
    (assert (equal *mid_max_seq* expect))))

python的实现:

# -*- coding: utf-8 -*-
import bisect
import random
mid_max_seq = [] #用于保存递归的中间结果
#题目:给定一个 array,array中数字不重复,求出里面最长的连续的一段,它由连续的数组成,顺序任意。
#解决思路:采用分治法,从中间将数组分成两段,分别计算左边,右边,以及从中间开始的连续数字,取三者中最长。左边和右边采用递归(get_max_seq),中间采用向左右扩张计算(get_max_mid_seq)。
def test():
    '''测试'''
    li = [  
            {'q':[], 'a':[]}, 
            {'q':[1], 'a':[1]}, 
            {'q':[1, 0], 'a':[0, 1]}, 
            {'q':[2, 1, 0], 'a':[0, 1, 2]},
            {'q':[7, 4, 3, 1, 2, 0, 9, 8, 10, 6 ], 'a':[0, 1, 2, 3, 4]},
            {'q':[7, 4, 3, 1, 5, 0, 9, 8, 10, 6 ], 'a':[8, 9, 10]},
            {'q':[9, 6, 3, 7, 0, 2, 1, 5, 8, 4], 'a':range(10)},
          ]
    for i in range(100):
        li.append(genTestData())
    for qa in li:
        print '---------solve problem: ', qa
        global mid_max_seq
        mid_max_seq = []
        result = get_max_seq(qa['q'])
        result.sort()
        assertEqual(result, qa['a'])

def genTestData():
    '''生成测试数据'''
    arr = range(10)
    random.shuffle(arr)
    return {'q':arr, 'a':range(10)}


def assertEqual(q, a):
    '''断言q和a相等'''
    if not q and not a:
        return
    #print 'assertEqual:q=', q, 'a=', a
    if len(q) != len(a):
        raise BaseException('q:%s shoule be equal than a:%s'%(q, a))
    for i in range(len(q)):
        if q[i] != a[i]:
            raise BaseException('q:%s shoule be equal than a:%s'%(q, a))

def get_max_seq(li):
    '''给定一个 array,array中数字不重复,求出里面最长的连续的一段,它由连续的数组成,顺序任意。
    >>> get_max_seq([5, 1, 3, 2])
    [1, 3, 2]
    >>> get_max_seq([5, 3, 1, 4, 2])
    [5, 3, 1, 4, 2]
    '''
    if len(li) == 0 or len(li)==1:
        return li;
    if len(set(li)) != len(li): #li是否有重复数字
        raise BaseException('should not have duplicate numbers')
    half = len(li)/2
    #print 'half:', half
    get_max_mid_seq (li, half-1, half+1)
    left_max_seq = get_max_seq( li[:half] )
    right_max_seq = get_max_seq( li[half:] )
    all = [left_max_seq, right_max_seq, mid_max_seq]
    max_len = max(map(lambda x:len(x), all))
    res = filter(lambda x:len(x)==max_len, all)
    if len(res) > 0:
        return res[0] 
    else:
        return []

def get_max_mid_seq(li, left, right):
    '''以left和right为中心向两边搜索最长连续数字'''
    if left < 0 or right > len(li):
        raise BaseException('error: left=%s, right=%s '%(left, right))
    #print 'get_max_mid_seq, li:', li, 'left:', left, 'right:', right
    if isSeq(li[left:right]):
        global mid_max_seq
        if len(li[left:right]) > len(mid_max_seq):
            mid_max_seq = li[left:right]
        #print 'save match:', mid_max_seq
        if left > 0:
            get_max_mid_seq(li, left-1, right)
        if right < len(li):
            get_max_mid_seq(li, left, right+1)            
    else:
        new_left, new_right = get_extend_limit(li, left, right)
        if new_left == left and new_right == right:
            return
        else:
            get_max_mid_seq(li, new_left, new_right)

def isSeq(li):
    '''判断li是否由连续数字组成
    >>> isSeq([2, 1, 3])
    True
    >>> isSeq([1, 2, 4])
    False
    '''
    if len(set(li)) != len(li):
        raise BaseException('li should not duplicated')
    return max(li) - min(li) == len(li)-1

def get_extend_limit(li, left, right):
    '''从li的left和right位置向左右扩展,知道将left和right之间
    >>> get_extend_limit([3, 5, 2, 6, 4, 1], 2, 4)
    (0, 5)
    >>> get_extend_limit([2, 5, 3, 6, 4, 1], 1, 4)
    (1, 5)
    '''
    #print 'get_extent_limit: li', li, 'left:', left, 'right:', right
    min_value = min(li[left:right])
    max_value = max(li[left:right])
    miss_numbers = filter( lambda x : x not in li[left:right], range( min_value, max_value ) )
    #print 'get_extend_limit: miss_number:%s'%(miss_numbers)
    if not miss_numbers:
        raise BaseException('miss_number should not be empty')
    if left>right:
        raise BaseException('get_extend_limit input error: left:%s, right:%s'%(left,right))
    new_left , new_right = left, right
    for value in li[:left]:
        if value in miss_numbers:
            new_left = li.index(value) 
            break
    for value in li[right:]:
        if value in miss_numbers:
            new_right = li.index(value)+1
    if new_left>new_right:
        raise BaseException('get_extend_limit return error: new_left:%s, new_right:%s'%(new_left,new_right))
    #print 'get_extent_limit, new_left:', new_left, 'new_right:', new_right
    return new_left, new_right

if __name__ == "__main__":
    import doctest
    doctest.testmod()
    test()


华为OD机试 - 仿LISP运算(Python 纯逻辑题,难点在于将括号中的片段截取出来,我的处理方案是,遍历输入的每一个字符,当遇到")"时,则在其前面必然存在一个“(”,找到其前面第一个“(”,然后截取“(”")"之间的内容(从栈中截取走),进行计算,将结果回填如栈中。) ,当前 OP 类型为 add / sub / mul / div(全小写),分别代表整数的加减乘除法,简单起见,所有 OP 参数个数均为 2。其中第一个元素 OP 为操作符,后续元素均为其参数,参数个数取决于操作符类型。除零错误时,输出 “error”, 阅读详情

相关推荐

华为OD机试题目详解:LISP表达式计算问题——基于Python、Java、JavaScript及C++多语言实现

在这篇文章中,我们详细解析了华为 OD 机试中有关 LISP 表达式计算的问题。通过使用 Python、Java、JavaScript C++ 四种语言,我们展示了如何使用栈结构递归解析嵌套的表达式,并处理不同运算符的计算。每种语言的实现虽然有细微的差别,但解题思路基本一致。括号嵌套问题:通过栈结构,我们可以轻松处理嵌套表达式。遇到左括号时压栈,遇到右括号时弹栈并执行相应的运算。除零问题:程序中需要明确处理除零情况,遇到除数为零时立即返回错误信息。输入解析。

m0_57781768的博客 378

python lisp_给 Lisp 程序员的 Python 简介

这是一篇为Lisp程序员写的Python简介(一些Python程序员告诉我,这篇文章对他们学习Lisp也有帮助,尽管这不是我的本意)。基本上,Python可以看作一个拥有“传统”语法(Lisp社区称之为“中缀”或者“m-lisp”语法)的Lisp方言。一个来自comp.lang.python的帖子说到“我一直不明白为什么LISP一个不错的想法,直到我开始玩上了Python”。Python支持除了...

weixin_39767887的博客 349

【华为OD机试真题 Python】仿LISP运算

LISP语言唯一的语法就是括号要配对。 形如 (OP P1 P2 …),括号内元素由单个空格分割。 其中第一个元素OP为操作符,后续元素均为其参数,参数个数取决于操作符类型 注意:参数 P1, P2 也有可能是另外一个嵌套的 (OP P1 P2 …) 当前OP类型为add/sub/mul/div(全小写),分别代表整数的加减乘除法。 简单起见,所以OP参数个数为2 举例 - 输入:(mul 3 -7)输出:-21 - 输入:(add 1 2) 输出:3 - 输入:(sub (mul 2 4

A_D_I_D_A_S的博客 777

pythonlisp学哪个好_五位专家跟你讲讲为啥Python更适合做AI/机器学习

摘要: 为什么Python会在这股深度学习浪潮中成为编程语言的头牌?听听大牛如何解释吧!1.Python网络编程框架Twisted的创始人Glyph Lefkowitz(glyph):编程是一项社交活动——Python社区已经认识到了这一点!人工智能是一个全面的技术术语,通常意味着当前计算机科学研究中最先进的领域。有一段时间,我们理所当然的认为基本图遍历是AI。那时候,Lisp是人工智能的专属语言...

weixin_39834406的博客 688

pythonlisp学哪个好_Lisp 值得去学习吗?

在 ILC 2002 大会上前Lisp大神,当今的Python倡导者Peter Norvig,由于某些原因,做一个类似于马丁路德在梵蒂冈宣扬新教的主题演讲,因为他在演讲中大胆地声称Python就是一种Lisp。讲完后进入提问环节,出乎我意料的是,Peter点了我过道另一侧,靠上面几排座位的一个老头,他衣着皱褶,在演讲刚开始的时候踱步进来,然后就靠在了那个座位上面。这老头满头凌乱的白发,邋遢的白胡须...

weixin_35688434的博客 1120

PythonLisp的元编程对话:宏与装饰器的跨时空技术融合

在这场元编程的进化之旅中,Lisp的宏系统Python的装饰器代表了两种截然不同却又互补的哲学思想。在技术不断演进的世界中,Lisp宏与Python装饰器的对话将继续启发我们创造更强大、更优雅的元编程系统。LispPython装饰器代表了元编程光谱的两端:一端是强大而灵活的编译时代码转换,另一端是优雅而明确的运行时函数包装。元编程是一场永恒的对话,而这场对话才刚刚开始。在这个示例中,我们结合了装饰器的运行时能力与契约式设计的思想,创建了一个强大的验证系统,展示了元编程如何增强代码的可靠性表达能力。

司徒鸿的博客 1068

2、引入Hy编程语言:LispPython的完美结合

本文介绍了Hy编程语言的基础知识及其与Python的无缝互操作特性,通过多个实际示例展示了Hy在Web开发、数据可视化、网络爬虫、深度学习自然语言处理等领域的应用。同时,文章还探讨了Hy与Clojure的相似性及差异,并提供了丰富的代码片段帮助读者快速上手Hy编程语言。

weixin_35749786的博客 764

华为OD机试-仿LISP运算

【代码】华为OD机试-仿LISP运算。

SD_JZZ的博客 298

笔试算法题记录2

1.给定一组元素个数不定的字符串数组,每个字符串的长度不定;请统计出该字符串数组中的英文字母子串、数字子串其他字符子串的总数; 输出为以","符号分隔3个数值,分别代表英文字母子串、数字子串其他字符子串的数量; 实现时无需考虑非法输入。 输入描述:输入为:字符串数组 例子:abcd1244!! BKMKLK0987% 输出描述:输出为以","符号分隔3个数值,分别代表英文字母...

dbvz4901的博客 196

python实习做什么工作-大一/大二学生Python实习的困惑?

题主是一名非名校的CS本科学生,现在遇到了一些困惑,想请教一下热心的segmentfault网友。因为不是985/211名校,现在题主所在的这所学校我感觉学风非常不好,第一是整体水平太低,一学期结束了,班上都没几个人能用C语言写出链表来,第二是ACM校队也是没有什么价值,C9的学生喜欢膜来膜去的还情有可原,但是我们这种学校都互膜成为一种风气,非常的不自在,学不到有价值的东西。其实一开始自己是学Ja...

weixin_37988176的博客 930

算法题Python常用内置函数、方法、技巧汇总(其三:字符串)

60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁。数字,所以是不能够判断负数的,在使用该方法时要注意这个问题,以免错判。如果我们确定字符串不会存在数字其他字符混搭的情况,我们可以只取字符串的最后一个元素进行判断。每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到1v1同样的学习效果!方法用以判断字符串中是否均为字母数字,根据判断结果返回一个布尔类型。

weixin_48157259的博客 1213

2026全网最新华为OD机试真题目录A+B+C+D+E卷(持续收录中)-Python

🔔本文收录于「最新最全华为OD机试真题(Python版)」专栏,手把手带你零基础教学华为OD机试。本题集提供最优题解思路,解题步骤,代码解析,复杂度分析及最优题解源码等,支持多语言题解,助你轻松拿捏OD机考,一举上岸!安利大家关注&&收藏&&订阅!题库正在疯狂收录中,up!up!up!! 🚫提醒:拒绝一切代考/替考,违法必究!本人所写题库均精心搜集于互联网。    💗订阅福利:一次订阅,可永久免费阅读,提供在线答疑解惑,后续题库更新皆可阅读使用!

**My Coding Family** 10万+

华为OD机试2025B卷统一考试题库清单(持续收录中)以及考点说明(Python/JS/GO/C++/JAVA)

华为OD机试2025B卷统一考试题库清单 以及考点说明,包含Python/JS/GO/C++/JAVA源码实现以及详细实现思路讲解,提供在线OJ在线编码、提交评测,模拟真实 华为OD 上机考试真实环境

2501_92522252的博客 1924

大二python考试题_大一/大二学生Python实习的困惑?

题主是一名非名校的CS本科学生,现在遇到了一些困惑,想请教一下热心的segmentfault网友。因为不是985/211名校,现在题主所在的这所学校我感觉学风非常不好,第一是整体水平太低,一学期结束了,班上都没几个人能用C语言写出链表来,第二是ACM校队也是没有什么价值,C9的学生喜欢膜来膜去的还情有可原,但是我们这种学校都互膜成为一种风气,非常的不自在,学不到有价值的东西。其实一开始自己是学Ja...

weixin_39629129的博客 295

112 - Tree Summing

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33850015的博客 161

2025华为OD机试2025B卷机考真题库清单 (全真题库) 含考点说明(华为OD2025年B卷)持续更新

2025华为OD机试2025B卷机考真题库清单 (全真题库) 含考点说明(华为OD2025年B卷)持续更新 提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解

2501_92522252的博客 1974

2026华为OD机试(Python)真题【E卷+A卷+B卷+C卷+D卷】目录+在线OJ

华为OD机试真题题库【E卷+A卷+B卷+C卷+D卷】目录,Python实现

MISAYAONE的博客 28万+

【全网最新OD题库】2026华为 OD 机试C卷 机考真题库清单(全真题库)含考点说明(华为OD+2025年C卷+2025年B卷+2025年A卷+E卷+D卷+C卷)

华为od机试,华为od机试真题,华为od机试E卷,华为odE卷,华为od机试真题E卷,华为OD,华为OD机试,华为OD机试真题,华为od机考,华为od机试D卷,华为od机试真题D卷,华为od手撕代码,华为od,华为od机试C卷,华为od e卷,华为2024e卷,od机试,2024E卷,华为OD机试E卷,什么是华为od,华为od介绍,全面了解华为od,2024华为od,如何备战华为od,华为od算法,华为od手撕代码,华为OD机试2024年最新题库,一文带你读懂华为OD,华为机试e卷,华为OD2025B卷、华

KJ.JK 3万+
pythonzhou
博客等级 码龄20年 0粉丝 1原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值