LeetCode刷题笔记(1):C#的哈希表
在刷题的时候遇到了比暴力搜索跟有效的哈希表,此前对哈希表所知不多,因此特来学习
哈希表
在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似[key,value]的键值对,其中key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。Hashtable中[key,value]键值对均为object类型,所以Hashtable可以支持任何类型的[key,value]键值对.
啥时候用哈希表
(1)某些数据会被高频率查询
(2)数据量大
(3)查询字段包含字符串类型
(4)数据类型不唯一
哈希表的使用
namespace
using System.Collections;
using System.Collections.Generic;
哈希表的基本方法:
//添加一个keyvalue键值对:
HashtableObject.Add(key,value);
//移除某个keyvalue键值对:
HashtableObject.Remove(key);
//移除所有元素:
HashtableObject.Clear();
// 判断是否包含特定键key,是返回True,否返回False
HashtableObject.ContainsKey(key);
// 判断是否包含特定键value,是返回True,否返回False
HashtableObject.ContainsValue(value);
将哈希表的内容赋值给一个变量时,参照下面格式
首先有一个哈希表,里面存有两个(key,value)对
hashtable.Add("姓名","不知道");
hashtable.Add("性别","男");
string name = (string)hashtable["姓名"];
Console.WriteLine(name);
//将哈希表的数据复制时,需要格式:(转换类型)对象[数据]
int ManOrWoman = (int)hashtable["性别"];
Console.WriteLine(ManOrWoman);
遍历哈希表
for(DictionaryEntry de in hashtable) //hashtable为一个Hashtable实例
{
Console.WriteLine(de.Key); //de.Key对应于keyvalue键值对key
Console.WriteLine(de.Value); //de.Key对应于keyvalue键值对value
}
遍历键(key)
foreach (int key in hashtable.Keys)
{
Console.WriteLine(key);
}
遍历值(value)
foreach (string value in hashtable.Values)
{
Console.WriteLine(value);
}
对哈希表进行排序
ArrayList akeys=new ArrayList(hashtable.Keys);
akeys.Sort(); //按字母顺序进行排序
foreach(string key in akeys)
{
Console.WriteLine(key + ": " + hashtable[key]); //排序后输出
}
从上面代码可以看出,哈希表的使用有点类似数组,哈希表对象后中括号的数字(或者其他的key)就是一个索引
Hashtable和Dictionary的对比
命名空间
Hashtable:System.Collections
Dictionary:System.Collections.Generic
效率
从大佬代码中看
using System.Collections.Generic;
using System.Collections;
using System;
Stopwatch sw = new Stopwatch();
Hashtable hashtable = new Hashtable();
Dictionary<string, int> dictionary = new Dictionary<string, int>();
int countNum = 1000000;
sw.Start();
for (int i = 0; i < countNum; i++)
{
hashtable.Add(i.ToString(), i);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds); //输出: 744
sw.Restart();
for (int i = 0; i < countNum; i++)
{
dictionary.Add(i.ToString(), i);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds); //输出: 489
sw.Restart();
for (int i = 0; i < countNum; i++)
{
hashtable.ContainsKey(i.ToString());
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds); //输出: 245
sw.Restart();
for (int i = 0; i < countNum; i++)
{
dictionary.ContainsKey(i.ToString());
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds); //输出: 192
从上面的时间对比来看,添加数据时Hashtable快。频繁调用数据时Dictionary快;原因可能在于Hashtable的(key,value)可以是object类型,而Dictionary<K,V>是泛型的,当 K/V是值类型时,所需要的空间和计算会更小
代入题目
我所做的这一题是比较简单的题目,只是由于可以用哈希表提高效率,因此拿来举例
//给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
//你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
两遍哈希的方法
第一遍把数据输进表中
第二遍查询表中数据是否符合条件
public int[] TwoSum(int[] nums, int target)
{
Dictionary<int, int> Dic = new Dictionary<int, int>();
for (int i = 0; i < nums.Length; i++)
{
Dic.Add(nums[i], i);
}
for (int i = 0; i < nums.Length; i++)
{
int complement = target - nums[i];
if (Dic.ContainsKey(complement) && Dic[complement] != i)
{
return new int[] { i, Dic[complement] };
}
}
return new int[] { 0, 0 };//如果以上没有得出一个数组,就返回[0,0],是返回值不为空
}
时间复杂度: O(n)
空间复杂度: O(n)