DAY6 哈希表01

哈希表理论基础

哈希表的概念

(hash table)是根据关键码的值而直接进行访问的数据结构。简单来讲,数组就是一张哈希表,哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素。

  • 一般哈希表都是用来快速判断一个元素是否出现集合里

哈希函数

哈希函数是一种将数据映射到固定大小值的函数。它接受输入数据并通过一系列计算将其转换为固定长度的哈希值或哈希码。哈希函数的输出通常是一个数字或一段固定长度的二进制字符串。

哈希碰撞

当两个及以上的数据都映射到了同一个索引下标的位置,就出现了哈希碰撞。
一般情况下哈希碰撞的解决方法有两种,拉链法和线性探测法。
拉链法就是选择适当的哈希表大小,这样既不会大量浪费内存,也不会因为链表太长而在查找上浪费太多时间。

242.有效的字母异位词

第一种思路的两个代码实现如下,这种思路本质上就是先把一个字符串放到一个列表中去,然后遍历字符串t中的字符,若字符存在在列表中,则删除。若不存在直接报错。最后如果把第一个字符串里的东西全删光了,就说明确实是有效的字母异位词。
非常蠢的思路,内存用了超级多。

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        hashA = []
        hashB = []
        for i in s:
            hashA.append(i)
        for j in t:
            if j in hashA:
                hashA.remove(j)
            else:
                hashB.append(j)
        return hashA == [] and not hashB

也是用了数组,但是内存占的很多。

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        n = list(t)
        for i in s:
            if i in n:
                n.remove(i)
            else:
                return False
        return not n

看了代码随想录的方法,确实我也想到了做一个26位哈希表,但以为这样会麻烦。显然我想错了
用相对值计算真的很聪明!!!

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        # 定义一个大小为26的数组。初始化为0
        # 这个数组record用来记录字符串s里字符出现的次数
        record = [0]*26
        for i in range(len(s)):
            record[ord(s[i])-ord("a")]+=1
        print(record)
        for i in range(len(t)):
            record[ord(t[i])-ord("a")]-=1
        for i in range(26):
            # record数组如果有的元素不为0,则说明字符串s和t肯定不是字母异位词
            if record[i]!=0:
                return False
                #如果有一个元素不为零,则可以判断字符串s和t不是字母异位词
                break
        return True

349. 两个数组的交集

利用集合的性质

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        a = set()
        for num1 in nums1:
            if num1 in nums2:
                a.add(num1)
        return list(a)

直接用set()函数中的方法

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        return list(set(nums1) & set(nums2))

202. 快乐数

总体思路:将每次生成的数字都检查是否在哈希表中,如果哈希表中已经有了这个数字,那么这个数字就不是快乐数。如果没有这个数字就将其放入哈希表。当数字为1时,这个原数字就是快乐数。(需定义一个实现当前数 数位分离求各位平方和的函数

class Solution:
    def isHappy(self, n: int) -> bool:
        # 将当前数进行数位分离,求各位上平方的和
        # 每次生成的数,查是否在哈希集合中,在的话就不是快乐数,不在的话就添加到集合里。

        # 使用集合记录过程数据
        record = set()

        while True:
            # 将当前这个数字替换为它每个位置上的数字的平方和
            n = self.getNext(n)
            if n ==1:
                return True
            if n in record:
                return False
            else:
                record.add(n)

    # 求正整数num每个位置的平方和 
    def getNext(self,num):
        happy_sum = 0
        while num:
            # 先取余得到num的低位数字 算出平方
            happy_sum += (num%10)**2
            # 再对10整除得到高一位的数字
            num = num//10
        return happy_sum

1. 两数之和

最蠢的暴力解法

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        for i in range(len(nums)):
            for j in range(1,len(nums)):
                if nums[i]+nums[j] == target and i != j:
                    return [i,j]

想到了target-nums[i]的思路

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        for i in range(len(nums)):
            value=target-nums[i]
            if value in nums and i!=nums.index(value):
                return [i,nums.index(value)]

第2种方法的升级版,内存减少了一些,使用了 python中的内置函数

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        # 利用哈希表的映射关系实现缩短寻找target-x
        hashlist = dict()
        # 用enumerate函数遍历数组的下标和值
        for i, num in enumerate(nums):
            if target-num in hashlist:
                return [i,hashlist[target-num]]
            # 数组的值作为键 下标作为值
            hashlist[nums[i]]=i
        return []
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一段Java代码实现: ```java import java.io.File; import java.io.FileNotFoundException; import java.util.Arrays; import java.util.HashMap; import java.util.Scanner; public class Billionaire { private String name; private String arriveDate; private String city; private double wealth; public Billionaire(String name, String arriveDate, String city, double wealth) { this.name = name; this.arriveDate = arriveDate; this.city = city; this.wealth = wealth; } public String getName() { return name; } public String getArriveDate() { return arriveDate; } public String getCity() { return city; } public double getWealth() { return wealth; } public static void main(String[] args) { // 从文件中读取亿万富翁信息 String filename = "billionaires.txt"; Billionaire[] billionaires = readBillionairesFromFile(filename); // 按照到达日期排序 Arrays.sort(billionaires, (a, b) -> a.getArriveDate().compareTo(b.getArriveDate())); // 计算每个城市每天的财富总和 HashMap<String, Double> cityWealthMap = new HashMap<>(); String prevDate = ""; for (Billionaire billionaire : billionaires) { String cityDateKey = billionaire.getArriveDate() + "-" + billionaire.getCity(); if (!cityWealthMap.containsKey(cityDateKey)) { cityWealthMap.put(cityDateKey, 0.0); } if (!prevDate.equals("")) { double wealthPerDay = billionaire.getWealth() / daysBetween(prevDate, billionaire.getArriveDate()); for (String dateKey : getDateKeysBetween(prevDate, billionaire.getArriveDate(), billionaire.getCity())) { cityWealthMap.put(dateKey, cityWealthMap.get(dateKey) + wealthPerDay); } } prevDate = billionaire.getArriveDate(); } // 输出每个城市每天的财富总和 for (String cityDateKey : cityWealthMap.keySet()) { System.out.println(cityDateKey + ": " + cityWealthMap.get(cityDateKey)); } // 输出按照到达日期排序后的亿万富翁列表 for (Billionaire billionaire : billionaires) { System.out.println(billionaire.getName() + ": " + billionaire.getArriveDate() + " " + billionaire.getCity() + " " + billionaire.getWealth()); } } // 从文件中读取亿万富翁信息 private static Billionaire[] readBillionairesFromFile(String filename) { try { Scanner scanner = new Scanner(new File(filename)); int n = scanner.nextInt(); scanner.nextLine(); // 读取换行符 Billionaire[] billionaires = new Billionaire[n]; for (int i = 0; i < n; i++) { String line = scanner.nextLine(); String[] parts = line.split(" "); billionaires[i] = new Billionaire(parts[0], parts[1], parts[2], Double.parseDouble(parts[3])); } scanner.close(); return billionaires; } catch (FileNotFoundException e) { e.printStackTrace(); return null; } } // 计算两个日期之间相差的天数 private static int daysBetween(String date1, String date2) { int year1 = Integer.parseInt(date1.substring(0, 4)); int month1 = Integer.parseInt(date1.substring(5, 7)); int day1 = Integer.parseInt(date1.substring(8, 10)); int year2 = Integer.parseInt(date2.substring(0, 4)); int month2 = Integer.parseInt(date2.substring(5, 7)); int day2 = Integer.parseInt(date2.substring(8, 10)); int days1 = getDaysFromYearStart(year1, month1, day1); int days2 = getDaysFromYearStart(year2, month2, day2); return Math.abs(days2 - days1); } // 计算某年某月某日是该年的第几天 private static int getDaysFromYearStart(int year, int month, int day) { int[] daysInMonth = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int days = day; for (int i = 1; i < month; i++) { days += daysInMonth[i]; } if (month > 2 && isLeapYear(year)) { days++; } return days; } // 判断某年是否为闰年 private static boolean isLeapYear(int year) { return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; } // 获取两个日期之间的所有日期对应的哈希表键 private static String[] getDateKeysBetween(String date1, String date2, String city) { int year1 = Integer.parseInt(date1.substring(0, 4)); int month1 = Integer.parseInt(date1.substring(5, 7)); int day1 = Integer.parseInt(date1.substring(8, 10)); int year2 = Integer.parseInt(date2.substring(0, 4)); int month2 = Integer.parseInt(date2.substring(5, 7)); int day2 = Integer.parseInt(date2.substring(8, 10)); int days1 = getDaysFromYearStart(year1, month1, day1); int days2 = getDaysFromYearStart(year2, month2, day2); int diff = days2 - days1; String[] dateKeys = new String[diff + 1]; for (int i = 0; i <= diff; i++) { int currYear = year1; int currMonth = month1; int currDay = day1 + i; if (currDay > 31 && (currMonth == 1 || currMonth == 3 || currMonth == 5 || currMonth == 7 || currMonth == 8 || currMonth == 10 || currMonth == 12)) { currDay -= 31; currMonth++; } else if (currDay > 30 && (currMonth == 4 || currMonth == 6 || currMonth == 9 || currMonth == 11)) { currDay -= 30; currMonth++; } else if (currDay > 28 && currMonth == 2 && !isLeapYear(currYear)) { currDay -= 28; currMonth++; } else if (currDay > 29 && currMonth == 2 && isLeapYear(currYear)) { currDay -= 29; currMonth++; } if (currMonth > 12) { currMonth = 1; currYear++; } dateKeys[i] = String.format("%04d-%02d-%02d-%s", currYear, currMonth, currDay, city); } return dateKeys; } } ``` 请注意,上述代码只是一个示例,可能需要根据实际情况进行修改和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值