1.斐波那契三角形
# 斐波那契三角形
# [1]
# [1, 1, 1]
# [1, 1, 2, 1, 1]
# [1, 1, 2, 3, 2, 1, 1]
# [1, 1, 2, 3, 5, 3, 2, 1, 1]
# [1, 1, 2, 3, 5, 8, 5, 3, 2, 1, 1]
# [1, 1, 2, 3, 5, 8, 13, 8, 5, 3, 2, 1, 1]
def fib(n):
if n == 1:
return 1
if n == 2:
return 1
if n > 2:
return fib(n - 1) + fib(n - 2)
def listfib(n):
alist = []
for i in range(1, n + 1):
alist.append(fib(i))
return alist
def fib_three(n):
for i in range(1, n + 1):
if i <= 1:
print(listfib(i))
else:
print(listfib(i) + listfib(i)[0:i - 1][::-1])
fib_three(7)
2.两数之和,链表相加,不含重复字符的最长子串
# 题目:
#
# 给定一个整数数列,找出其中和为特定值的那两个数。
#
# 你可以假设每个输入都只会有一种答案,同样的元素不能被重用。
#
# 示例:
#
# 给定 nums = [2, 7, 11, 15], target = 9
#
# 因为 nums[0] + nums[1] = 2 + 7 = 9
# 所以返回 [0, 1]
def twoSum1(nums, target):
hashmap = {}
for index, num in enumerate(nums):
another_num = target - num
if another_num in hashmap:
return [hashmap[another_num], index]
else:
hashmap[num] = index
return None
alist = [2, 7, 11, 15]
print(twoSum1(alist, 18))
# 链表(linked list)是由一组被称为结点的数据元素组成的数据结构,每个结点都包含结点本身的信息和指向下一个结点的地址。
# 由于每个结点都包含了可以链接起来的地址信息,所以用一个变量就能够访问整个结点序列。也就是说,
# 结点包含两部分信息:一部分用于存储数据元素的值,称为信息域;另一部分用于存储下一个数据元素地址的指针,称为指针域。
# 链表中的第一个结点的地址存储在一个单独的结点中,称为头结点或首结点。链表中的最后一个结点没有后继元素,其指针域为空。
# 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储 一位 数字。
# 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
# 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
# 输出:7 -> 0 -> 8
# 原因:342 + 465 = 807
# Definition for singly-linked list.
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
# 你可以实现一些链表的增删等操作
# 初始化创建一个ListNode(0),next指向求和后的结果
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
result = ListNode(0) # result是一个头指针,将其数据初始化为了0
r = result # r总是指向返回结果的链表的新元素
carry = 0 # carry表示进位
# 循环进行对应位相加
while (l1 or l2):
x = (l1.val if l1 else 0) # 如果l1有数据,则x为该数据,否则为0
y = (l2.val if l2 else 0) # 如果l2有数据,则y为该数据,否则为0
s = carry + x + y
carry = s // 10 # 得到进位(0或1)
r.next = ListNode(s % 10) # 新建一个节点,并保存该位的运算结果
r = r.next # r与r.next将指向同一个内存地址
# 将“指针”向后移动
if l1 != None:
l1 = l1.next
if l2 != None:
l2 = l2.next
# 判断最高位相加后是否有进位,有进位则新建一个节点保存进位‘1’
if (carry > 0):
r.next = ListNode(1)
return result.next # 注意:这里返回的是result.next,而不是result。因为result是头指针,没有真正保存有效的数据
#个人理解
def add_num(l1, l2):
first_node = ListNode(0) # 创建一个初始节点为0
cur = first_node # 创建一个指针指向当前节点,初始化时指向first_node
jinwei = 0 # 相加后超过10的进位
while l1 or l2:
# 获取到初始节点的值
num1 = l1.val if l1 else 0
num2 = l2.val if l2 else 0
# 每一个位上的和为对应值加上前一位进位
sum_num = num1 + num2 + jinwei
# 进位为和除以10的商
jinwei = sum_num // 10
# 余数为当前节点的下一个节点
cur.next = ListNode(sum_num % 10)
# 重置l1,l2,cur,进行下轮循环
l1 = l1.next if l1 else None
l2 = l2.next if l2 else None
cur = cur.next
# 循环完成后最高位如果还有进位
if jinwei > 0:
cur.next = ListNode(jinwei)
# 返回值为第一个节点0的下一个节点
return first_node.next
num1 = ListNode(2)
num1.next = ListNode(4)
num1.next.next = ListNode(3)
num2 = ListNode(5)
num2.next = ListNode(6)
num2.next.next = ListNode(4)
solution = Solution()
result = solution.addTwoNumbers(num1, num2)
print(result.val, result.next.val, result.next.next.val)
# 假设一个不存在重复元素的正序数组,但是数组在某个未知的位置进行了旋转,例如
# [1,2,3,4,5,6,7,8,9]旋转后为[4,5,6,7,8,9,1,2,3]
# 搜索给定数值在数组中的索引,不存在返回-1,时间复杂度o(log n)级别
def find_index(alist, target):
left_index = 0
right_index = len(alist) - 1
if target == alist[left_index]:
return 0
if target == alist[right_index]:
return len(alist) - 1
for i in range(len(alist)):
if target > alist[left_index]:
left_index += 1
if target == alist[left_index]:
return left_index
if target <= alist[right_index]:
right_index -= 1
if target == alist[right_index]:
return right_index
else:
return -1
alist = [4, 5, 6, 7, 8, 9, 1, 2, 3]
print(find_index(alist, 1))
# 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度
# 思路:定义一个变量指向最长子串的起始位置,定义一个变量表示最长子串长度,定义一个字典存放不重复的元素及其下标
def lengthOfLongestSubstring(s):
"""
:type s: str
:rtype: int
"""
start = 0
usedChar = {} # 记录每个元素和它最后一次出现位置
max_len = 0 # 记录最长子串长度
for i in range(len(s)):
# 如果第i个元素在字典中并且第i个元素在表中索引大于等于start,
if s[i] in usedChar and usedChar[s[i]] >= start:
start = usedChar[s[i]] + 1
# 如果第i个元素不在字典中
else:
max_len = max(max_len, i - start + 1) # 最长子串长度取之前最长的长度和
usedChar[s[i]] = i # 1.如果没有在字典中,将第i元素加入到字典中2.如果已经在字典中了,就更改value值
return max_len
print(lengthOfLongestSubstring("a123456"))
3.寻找数组中心索引
# 寻找数组的中心索引
# 给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法。
#
# 我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。
#
# 如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。
# 输入:
# nums = [1, 7, 3, 6, 5, 6]
# 输出: 3
# 解释:
# 索引3 (nums[3] = 6) 的左侧数之和(1 + 7 + 3 = 11),与右侧数之和(5 + 6 = 11)相等。
# 同时, 3 也是第一个符合要求的中心索引。
# 以 [1, 7, 3, 6, 5, 6] 为例,6 为中心索引为 i 的元素 j,左侧和 left_sum 为 11,右侧和 right_sum 也为 11。
#
# 所以可以将数组表示为 [left_sum, j, right_sum] ,而且left_sum = right_sum ,设数组所有元素和为 total ,
# 则有式子 2*left_sum + j = total 成立,以此条件判断是否为中心索引。
def find_center_index(nums):
sum_nums = sum(nums)
left_sum = 0
for i, j in enumerate(nums):
if 2 * left_sum + j == sum_nums:
return i
left_sum += j
return -1
nums = [1, 7, 3, 6, 5, 6]
print(find_center_index(nums))
nums = [i for i in range(100)]
import random
random.shuffle(nums)
print(nums)
print(find_center_index(nums))
4.约瑟夫问题
#!usr/bin/python
# -*- coding: utf-8 -*-
# 约瑟夫斯问题(Josephus Problem)是应用队列(确切地说,是循环队列)的典型案例。在 约瑟夫斯问题 中,参与者围成一个圆圈,从某个
# 人(队首)开始报数,报数到n+1的人退出圆圈,然后从退出人的下一位重新开始报数;重复以上动作,直到只剩下一个人为止。
# 思路:使用队列先进先出特性,将报的n个数的人从队列中删除,然后添加到对尾,此时第一个人就是第一次计数后将要退出的人,将它退出,第一轮结束
# 此后每轮都依次进行即可
class Queue:
def __init__(self):
self.items = []
def enqueue(self, item):
self.items.append(item)
def dequeue(self):
return self.items.pop(0)
def empty(self):
return self.size() == 0
def size(self):
return len(self.items)
def printquene(queue):
for i in queue.items:
print(i, end=",")
def josephus(namelist, num):
simqueue = Queue()
for name in namelist:
simqueue.enqueue(name)
while simqueue.size() > 1:
for i in range(num):
simqueue.enqueue(simqueue.dequeue())
printquene(simqueue)
print()
simqueue.dequeue()
return simqueue.dequeue()
if __name__ == '__main__':
print(josephus(["Bill", "David", "Kent", "Jane", "Susan", "Brad","java"], 3))
# Jane,Susan,Brad,Bill,David,Kent,
# David,Kent,Susan,Brad,Bill,
# Bill,Kent,Susan,Brad,
# Kent,Susan,Brad,
# Brad,Susan,
# Susan
5.