第八章 Data Structue

211-字符串置换

描述

给出一个不含重复数字的排列,求这些数字的所有排列按字典序排序后该排列的编号。其中,编号从1开始。

样例

“abc” 为 “cba” 的置换。
“aabc” 不是 “abcc” 的置换。


def Permutation_2(A,B):
    from collections import Counter
    return Counter(A)==Counter(B)

a = input()
b = input()
print(Permutation_2(a,b))
  1. 哈希函数
    中文English
    在数据结构中,哈希函数是用来将一个字符串(或任何其他类型)转化为小于哈希表大小且大于等于零的整数。一个好的哈希函数可以尽可能少地产生冲突。一种广泛使用的哈希函数算法是使用数值33,假设任何字符串都是基于33的一个大整数,比如:

hashcode(“abcd”) = (ascii(a) * 333 + ascii(b) * 332 + ascii© *33 + ascii(d)) % HASH_SIZE

                          = (97* 333 + 98 * 332 + 99  *  33 +100) % HASH_SIZE

                          = 3595978 % HASH_SIZE

其中HASH_SIZE表示哈希表的大小(可以假设一个哈希表就是一个索引0 ~ HASH_SIZE-1的数组)。

给出一个字符串作为key和一个哈希表的大小,返回这个字符串的哈希值。

Example
样例 1:

输入: key = “abcd”, size = 1000
输出: 978
样例解释:(97 * 33^3 + 9833^2 + 9933 + 100*1)%1000 = 978
样例 2:

输入: key = “abcd”, size = 100
输出: 78
样例解释:(97 * 33^3 + 98 * 33 ^2 + 99 * 33 + 100*1)%100 = 78
Clarification
对于这个问题,您没有必要设计自己的哈希算法或考虑任何冲突问题,您只需要按照描述实现算法.

小技巧,如何计算a * 33^3 + b * 33^2 + c * 33 + d

sum = a
sum = (a * 33+b)
sum = (a * 33 + b ) * 33+c
sum = (a * 33^2 + b * 33 + c ) * 33 +d

链接:https://www.jianshu.com/p/9a67268b5a94


def hashcode(key,hash_size):
    prime=33
    hashcode=0
    for c in key:
        hashcode=(hashcode*prime+ord(c))%hash_size
    return hashcode

A=input()
b = int(input())
print(hashcode(A,b))

613—优秀成绩
每个学生有两个属性id和scores。找到每个学生最高的5个分数的平均值。

样例

给出 results = [[1,91],[1,92],[2,93],[2,99],[2,98],[2,97],[1,60],[1,58],[2,100],[1,61]]
返回:
1: 72.40
2: 97.40

思路

topK问题,K等于5

#哈希表+堆hash+heap
#2019/9/9
#考察哈希表的使用方法
#哈希表键值为id ,值为成绩数组
#学会遍历hash表的键值对,使用hash.items()
import heapq
import sys
from collections import defaultdict

class Record:
    def __init__(self,id,score):
        self.id = id
        self.score = score

class Solution:

    def highFive(self,result):

        scoresById = defaultdict(list)
        for id,score in result:
            scores = scoresById[id]
            heapq.heappush(scores,score)
            if len(scores) > 5:
                heapq.heappop(scores) #把最小的吐出来

        result = {}
        for id, scores in scoresById.items():
            if len(scores) == 5:
                result[id] = sum(scores)/5
        print(result)
        return result


if __name__ =='__main__':
    # n  = int(sys.stdin.readline())
    # info = []
    a = Solution()
    info =  [[1,91],[1,92],[2,93],[2,99],[2,98],[2,97],[1,60],[1,58],[2,100],[1,61]]
    a.highFive(info)

  1. K个最近的点
    中文English
    给定一些 points 和一个 origin,从 points 中找到 k 个离 origin 最近的点。按照距离由小到大返回。如果两个点有相同距离,则按照x值来排序;若x值也相同,就再按照y值排序。

Example
例1:

输入: points = [[4,6],[4,7],[4,4],[2,5],[1,1]], origin = [0, 0], k = 3
输出: [[1,1],[2,5],[4,4]]
例2:

输入: points = [[0,0],[0,9]], origin = [3, 1], k = 1
输出: [[0,0]]

https://github.com/tt66/LintCode/blob/master/K%E4%B8%AA%E6%9C%80%E8%BF%91%E7%9A%84%E7%82%B9-612-1.md

https://leetcode-cn.com/articles/k-closest-points-to-origin/

// An highlighted block
var foo = 'bar';

https://www.geeksforgeeks.org/find-k-closest-points-to-the-origin/

606 第k大的元素2
找到数组中第K大的元素,N远大于K

注意事项

你可以改变数组中元素的位置

样例

在数组 [9,3,2,4,8] 中, 第三大的元素是 4。
在数组 [1,2,3,4,5] 中, 第一大 的元素是 5,第二大 的元素是 4,第三大 的元素是3等等。

import heapq
import sys
class Solution:

    def kthLargestElement2(self,nums,k):
        if not nums:
            raise Exception()

        heap = []
        for num in nums:
            heapq.heappush(heap,num)
            if len(heap)> k:
                heapq.heappop(heap) #每次弹出k个中最小的值。
        print(heap[0])
        return heap[0]


nums = [int(x) for x in sys.stdin.readline().split()]
k = int(input())
a = Solution()
a.kthLargestElement2(nums,k)

461—无序数组中第k小的元素
描述

找到一个无序数组中最小的K个数

样例

[3, 4, 1, 2, 5], k = 3, 最小的三个数字为[1, 2, 3]

挑战

O(nlogn)的非常简单,是否可以O(n)

思路

同第k大元素那题,唯一区别在于将quickSelect时数组按升序排列

import heapq
import sys
class Solution:
    def kthSmallest(self,k,nums):
        if not nums:
            return -1
        heap = []
        for num in nums:
            heapq.heappush(heap,-num)
            if len(heap) > k:
                heapq.heappop(heap)
        print(-heap[0])
        return -heap[0]

nums = [int(x) for x in sys.stdin.readline().split()]
k = int(input())
a = Solution()
a.kthSmallest(k,nums)

  1. 前K大数
    中文English
    在一个数组中找到前K大的数

Example
样例1

输入: [3, 10, 1000, -99, 4, 100] 并且 k = 3
输出: [1000, 100, 10]
样例2

输入: [8, 7, 6, 5, 4, 3, 2, 1] 并且 k = 5
输出: [8, 7, 6, 5, 4]

import heapq
import sys
class Solution:
    def topk(self, nums, k):
        if not nums or k <=0:
            return []
        heap = []
        for num in nums:
            heapq.heappush(heap,num)
            if len(heap) > k:
                heapq.heappop(heap)

        result = []
        while heap:
            result.append(heapq.heappop(heap))
        return list(reversed(result))  #顺序递增变成逆序

nums = [int(x) for x in sys.stdin.readline().split()]
k = int(input())
a = Solution()
print(a.topk(nums,k))

  1. 重哈希
    中文English
    哈希表容量的大小在一开始是不确定的。如果哈希表存储的元素太多(如超过容量的十分之一),我们应该将哈希表容量扩大一倍,并将所有的哈希值重新安排。假设你有如下一哈希表:

size=3, capacity=4

[null, 21, 14, null]
↓ ↓
9 null

null
哈希函数为:

int hashcode(int key, int capacity) {
return key % capacity;
}
这里有三个数字9,14,21,其中21和9共享同一个位置因为它们有相同的哈希值1(21 % 4 = 9 % 4 = 1)。我们将它们存储在同一个链表中。

重建哈希表,将容量扩大一倍,我们将会得到:

size=3, capacity=8

index: 0 1 2 3 4 5 6 7
hash : [null, 9, null, null, null, 21, 14, null]
给定一个哈希表,返回重哈希后的哈希表。

Example
样例 1

输入 : [null, 21->9->null, 14->null, null]
输出 : [null, 9->null, null, null, null, 21->null, 14->null, null]
Notice
哈希表中负整数的下标位置可以通过下列方式计算:

C++/Java:如果你直接计算-4 % 3,你会得到-1,你可以应用函数:a % b = (a % b + b) % b得到一个非负整数。
Python:你可以直接用-1 % 3,你可以自动得到2。

// An highlighted block
var foo = 'bar';
  1. 合并k个排序链表
    中文English
    合并k个排序链表,并且返回合并后的排序链表。尝试分析和描述其复杂度。

Example
样例 1:
输入: [2->4->null,null,-1->null]
输出: -1->2->4->null

样例 2:
输入: [2->6->null,5->null,7->null]
输出: 2->5->6->7->null

https://github.com/qiwsir/algorithm/blob/master/heapq.md

// An highlighted block
var foo = 'bar';
  1. 丑数 II
    中文English
    设计一个算法,找出只含素因子2,3,5 的第 n 小的数。

符合条件的数如:1, 2, 3, 4, 5, 6, 8, 9, 10, 12…

Example
样例 1:

输入:9
输出:10
样例 2:

输入:1
输出:1
Challenge
要求时间复杂度为 O(nlogn) 或者 O(n)。

Notice
我们可以认为 1 也是一个丑数。

// An highlighted block
var foo = 'bar';
  1. 摊平二维向量
    中文English
    设计一个迭代器来实现摊平二维向量的功能

Example
例1:

输入:[[1,2],[3],[4,5,6]]
输出:[1,2,3,4,5,6]
例2:

输入:[[7,9],[5]]
输出:[7,9,5]

// An highlighted block
var foo = 'bar';
  1. LRU缓存策略
    中文English
    为最近最少使用(LRU)缓存策略设计一个数据结构,它应该支持以下操作:获取数据和写入数据。

get(key) 获取数据:如果缓存中存在key,则获取其数据值(通常是正数),否则返回-1。
set(key, value) 写入数据:如果key还没有在缓存中,则写入其数据值。当缓存达到上限,它应该在写入新数据之前删除最近最少使用的数据用来腾出空闲位置。
最终, 你需要返回每次 get 的数据.

Example
样例 1:

输入:
LRUCache(2)
set(2, 1)
set(1, 1)
get(2)
set(4, 1)
get(1)
get(2)
输出:[1,-1,1]
解释:
cache上限为2,set(2,1),set(1, 1),get(2) 然后返回 1,set(4,1) 然后 delete (1,1),因为 (1,1)最少使用,get(1) 然后返回 -1,get(2) 然后返回 1。
样例 2:

输入:
LRUCache(1)
set(2, 1)
get(2)
set(3, 2)
get(2)
get(3)
输出:[1,-1,2]
解释:
cache上限为 1,set(2,1),get(2) 然后返回 1,set(3,2) 然后 delete (2,1),get(2) 然后返回 -1,get(3) 然后返回 2。

// An highlighted block
var foo = 'bar';

  1. 前K大数 II
    中文English
    实现一个数据结构,提供下面两个接口
    1.add(number) 添加一个元素
    2.topk() 返回前K大的数

Example
样例1

输入:
s = new Solution(3);
s.add(3)
s.add(10)
s.topk()
s.add(1000)
s.add(-99)
s.topk()
s.add(4)
s.topk()
s.add(100)
s.topk()

输出:
[10, 3]
[1000, 10, 3]
[1000, 10, 4]
[1000, 100, 10]

解释:
s = new Solution(3);

生成了一个新的数据结构, 并且 k = 3.
s.add(3)
s.add(10)
s.topk()

返回 [10, 3]
s.add(1000)
s.add(-99)
s.topk()

返回 [1000, 10, 3]
s.add(4)
s.topk()

返回 [1000, 10, 4]
s.add(100)
s.topk()

返回 [1000, 100, 10]
样例2

输入:
s = new Solution(1);
s.add(3)
s.add(10)
s.topk()
s.topk()

输出:
[10]
[10]

解释:
s = new Solution(1);

生成了一个新的数据结构, 并且 k = 1.
s.add(3)
s.add(10)
s.topk()

返回 [10]
s.topk()

返回 [10]

// An highlighted block
var foo = 'bar';
  1. 合并k个排序数组
    中文English
    将 k 个有序数组合并为一个大的有序数组。

Example
样例 1:

输入:
[
[1, 3, 5, 7],
[2, 4, 6],
[0, 8, 9, 10, 11]
]
输出: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
样例 2:

输入:
[
[1,2,3],
[1,2]
]
输出: [1,1,2,2,3]
Challenge
在 O(N log k) 的时间复杂度内完成:

N 是所有数组包含的整数总数量。
k 是数组的个数。

https://wulc.me/2016/03/29/LeetCode%E8%A7%A3%E9%A2%98%E6%8A%A5%E5%91%8A(23)–%E5%90%88%E5%B9%B6k%E4%B8%AA%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84/

// An highlighted block
var foo = 'bar';
  1. 堆化
    中文English
    给出一个整数数组,堆化操作就是把它变成一个最小堆数组。

对于堆数组A,A[0]是堆的根,并对于每个A[i],A [i * 2 + 1]是A[i]的左儿子并且A[i * 2 + 2]是A[i]的右儿子。

Example
样例 1

输入 : [3,2,1,4,5]
输出 : [1,2,3,4,5]
解释 : 返回任何一个合法的堆数组
Challenge
O(n)的时间复杂度完成堆化

Clarification
什么是堆? 什么是堆化? 如果有很多种堆化的结果?

堆是一种数据结构,它通常有三种方法:push, pop 和 top。其中,“push”添加新的元素进入堆,“pop”删除堆中最小/最大元素,“top”返回堆中最小/最大元素。
把一个无序整数数组变成一个堆数组。如果是最小堆,每个元素A[i],我们将得到A[i * 2 + 1] >= A[i]和A[i * 2 + 2] >= A[i]
返回其中任何一个。

// An highlighted block
var foo = 'bar';
  1. 最长连续序列
    中文English
    给定一个未排序的整数数组,找出最长连续序列的长度。

Example
样例 1

输入 : [100, 4, 200, 1, 3, 2]
输出 : 4
解释 : 这个最长的连续序列是 [1, 2, 3, 4]. 返回所求长度 4
Clarification
要求你的算法复杂度为O(n)

// An highlighted block
var foo = 'bar';
  1. 嵌套列表的加权和
    中文English
    给一个嵌套的整数列表, 返回列表中所有整数由它们的深度加权后的总和. 每一个元素可能是一个整数或一个列表(其元素也可能是整数或列表)

Example
例1:

输入: the list [[1,1],2,[1,1]],
输出: 10.
解释:
four 1’s at depth 2, one 2 at depth 1, 4 * 1 * 2 + 1 * 2 * 1 = 10
例2:

输入: the list [1,[4,[6]]],
输出: 27.
解释:
one 1 at depth 1, one 4 at depth 2, and one 6 at depth 3; 1 + 4 * 2 + 6 * 3 = 27

// An highlighted block
var foo = 'bar';

494双队列实现栈

利用两个队列来实现一个栈的功能

样例

push(1)
pop()
push(2)
isEmpty() // return false
top() // return 2
pop()
isEmpty() // return true

// An highlighted block
var foo = 'bar';
  1. 左旋右旋迭代器
    中文English
    给你两个一维向量,实现一个迭代器,交替返回两个向量的元素

Example
样例1

输入: v1 = [1, 2] 和 v2 = [3, 4, 5, 6]
输出: [1, 3, 2, 4, 5, 6]
解释:
一开始轮换遍历两个数组,当v1数组遍历完后,就只遍历v2数组了,所以返回结果:[1, 3, 2, 4, 5, 6]
样例2

输入: v1 = [1, 1, 1, 1] 和 v2 = [3, 4, 5, 6]
输出: [1, 3, 1, 4, 1, 5, 1, 6]

// An highlighted block
var foo = 'bar';
  1. 左旋右旋迭代器 II
    中文English
    k 个一维向量,循环地返回向量中的元素

Example
样例1

输入: k = 3
vecs = [
[1,2,3],
[4,5,6,7],
[8,9],
]
输出: [1,4,8,2,5,9,3,6,7]
样例2

输入: k = 3
vecs = [
[1,1,1]
[2,2,2]
[3,3,3]
]
输出: [1,2,3,1,2,3,1,2,3]

// An highlighted block
var foo = 'bar';
  1. 岛屿的个数II
    中文English
    给定 n, m, 分别代表一个二维矩阵的行数和列数, 并给定一个大小为 k 的二元数组A. 初始二维矩阵全0. 二元数组A内的k个元素代表k次操作, 设第i个元素为 (A[i].x, A[i].y), 表示把二维矩阵中下标为A[i].x行A[i].y列的元素由海洋变为岛屿. 问在每次操作之后, 二维矩阵中岛屿的数量. 你需要返回一个大小为k的数组.

Example
样例 1:

输入: n = 4, m = 5, A = [[1,1],[0,1],[3,3],[3,4]]
输出: [1,1,2,2]
解释:
0. 00000
00000
00000
00000

  1. 00000
    01000
    00000
    00000
  2. 01000
    01000
    00000
    00000
  3. 01000
    01000
    00000
    00010
  4. 01000
    01000
    00000
    00011
    样例 2:

输入: n = 3, m = 3, A = [[0,0],[0,1],[2,2],[2,1]]
输出: [1,1,2,2]
Notice
设定0表示海洋, 1代表岛屿, 并且上下左右相邻的1为同一个岛屿.

// An highlighted block
var foo = 'bar';
  1. 摊平嵌套的列表
    中文English
    给你一个嵌套的列表,实现一个迭代器将其摊平。
    一个列表的每个元素可能是整数或者一个列表。

Example
样例1

输入: list = [[1,1],2,[1,1]]
输出: [1,1,2,1,1]
样例2

输入: list = [1,[4,[6]]]
输出: [1,4,6]
Notice
你不需要实现删除方法

// An highlighted block
var foo = 'bar';
  1. 最高频的K个单词
    中文English
    给一个单词列表,求出这个列表中出现频次最高的K个单词。

Example
样例 1:

输入:
[
“yes”, “lint”, “code”,
“yes”, “code”, “baby”,
“you”, “baby”, “chrome”,
“safari”, “lint”, “code”,
“body”, “lint”, “code”
]
k = 3
输出: [“code”, “lint”, “baby”]
样例 2:

输入:
[
“yes”, “lint”, “code”,
“yes”, “code”, “baby”,
“you”, “baby”, “chrome”,
“safari”, “lint”, “code”,
“body”, “lint”, “code”
]
k = 4
输出: [“code”, “lint”, “baby”, “yes”]
Challenge
用 O(n log k)的时间和 O(n) 的额外空间完成。

Notice
你需要按照单词的词频排序后输出,越高频的词排在越前面。如果两个单词出现的次数相同,则词典序小的排在前面。

// An highlighted block
var foo = 'bar';
  1. LFU缓存
    中文English
    LFU是一个著名的缓存算法
    对于容量为k的缓存,如果缓存已满,并且需要逐出其中的密钥,则最少使用的密钥将被踢出。
    实现LFU中的set 和 get

Example
输入:
LFUCache(3)
set(2,2)
set(1,1)
get(2)
get(1)
get(2)
set(3,3)
set(4,4)
get(3)
get(2)
get(1)
get(4)

输出:
2
1
2
-1
2
1
4

// An highlighted block
var foo = 'bar';
  1. LRU缓存策略
    中文English
    为最近最少使用(LRU)缓存策略设计一个数据结构,它应该支持以下操作:获取数据和写入数据。

get(key) 获取数据:如果缓存中存在key,则获取其数据值(通常是正数),否则返回-1。
set(key, value) 写入数据:如果key还没有在缓存中,则写入其数据值。当缓存达到上限,它应该在写入新数据之前删除最近最少使用的数据用来腾出空闲位置。
最终, 你需要返回每次 get 的数据.

Example
样例 1:

输入:
LRUCache(2)
set(2, 1)
set(1, 1)
get(2)
set(4, 1)
get(1)
get(2)
输出:[1,-1,1]
解释:
cache上限为2,set(2,1),set(1, 1),get(2) 然后返回 1,set(4,1) 然后 delete (1,1),因为 (1,1)最少使用,get(1) 然后返回 -1,get(2) 然后返回 1。
样例 2:

输入:
LRUCache(1)
set(2, 1)
get(2)
set(3, 2)
get(2)
get(3)
输出:[1,-1,2]
解释:
cache上限为 1,set(2,1),get(2) 然后返回 1,set(3,2) 然后 delete (2,1),get(2) 然后返回 -1,get(3) 然后返回 2。

// An highlighted block
var foo = 'bar';
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值