鄙人 刘天昊 csdn新用户 用博客来记录自己的学习过程也希望和网络上志同道合的朋友做一些交流
leetcode篇因为研究生本科都不是cs出生,所以自学数据结构,所有的leetcode都是c语言实现
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].
这是leetcode上的第一题看例子很容易明白题目的意思--给一个整形数组,给一目标值,找到和等于目标值的两个数字的索引;
PlanA:暴力AC--没什么好说的O(n2)的时间复杂度;
PlanB:散列表(哈希表)--主要思路,把所有的值存入哈希表中,因为a+b=target 所以查找只需要查找 target-a(或者target-b随意)就可以(注意避免重复)时间复杂度O(n),空间复杂度O(n);(还有一种更快的方案就是边查边找,这样可以很好的避免重复)
PlanC:先进行快排序,然后定义首尾指针*(nums+i)+*(nums+j),比目标大,尾指针--,比目标小,头指针++,这里做完你会发现你排序后的索引也已经改变,所以最终
采取结构体的快排序来保存索引时间复杂度O(nlogn);
PlanB代码:
这里是discuss里的一种方案我更改加理解的,非自己原创说明一声
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
typedef struct HashNode//定义结构体哈希表的结点
{
int pos;//定义一个结点存放位置信息
int key;//定义一个结点存放关键字
}HashNode;
typedef struct HashMap//定义结构体哈希表的映射
{
int size;//定义存放哈希表的大小
HashNode **storage;//定义二级结构体指针去存放一级结构体指针的地址
}HashMap;
HashMap* InitHash(int size)//初始化哈希表
{
HashMap *hashmap=(HashMap *)malloc(sizeof(HashMap));//定义结构体指针用来访问返回哈希表,并且为其动态申请内存
hashmap->size=size;//传入哈希表的大小
hashmap->storage=(HashNode **)calloc(size,sizeof(HashNode *));//定义一段连续的内存来存放一级指针(结构体node的地址)
return hashmap;//返回指向哈希表的指针
}
void HashSet(HashMap *hashmap,int pos,int key)
{
int addr=abs(key)%hashmap->size;//余数保留法addr是求出来的地址要理解
HashNode *node;//定义结构体指针指向存放位置和关键字的结构体
while((node=hashmap->storage[addr]))//发生冲突时(可以这么做的最主要原因是calloc)有点难但是要学会理解
{
if(addr<hashmap->size-1)//最简单的开放地址法
{
addr++;
}
else
{
addr=0;//从地址0处开始重新找位置存放
}
}
node=(HashNode *)malloc(sizeof(HashNode));//给结构体node申请动态内存
node->pos=pos;//存放位置信息
node->key=key;//存放关键字信息
hashmap->storage[addr]=node;//把node指针的地址给storage
}
HashNode * HashGet(HashMap *hashmap,int key)
{
int addr=abs(key)%hashmap->size;
HashNode *node;
while((node=hashmap->storage[addr]))//当storage中有数据时(即地址不为空找到数据)注意代码虽然和HashSet中一模一样但是含义完全不同
{
if(node->key==key)//关键字找到的数据一致
{
return node;
}
if(addr<hashmap->size-1)//继续找
{
addr++;
}
else
{
addr=0;//从地址0处开始重新找位置存放
}
}
return NULL;//没找到
}
int* twoSum(int* nums, int numsSize, int target)
{
HashMap *hashmap;//定义哈希表头
HashNode *hashnode;
int res=0;
hashmap=InitHash(2*numsSize);//初始化哈希表
for(int i=0;i<numsSize;i++)//存放内容
{
HashSet(hashmap,i,nums[i]);
}
for(int i=0;i<numsSize;i++)//查找目标
{
res=target-nums[i];
hashnode=HashGet(hashmap,res);
if(hashnode)
{
while(hashnode->pos!=i)
{
int *p;
p=(int *)malloc(2*sizeof(int));
p[0]=hashnode->pos;
p[1]=i;
return p;
}
}
}
exit(0);
}
PlanC代码
这里快排序的理解推荐纪磊的《啊哈!算法》很容易理解快排序
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
typedef struct Array//定义结构体保存索引
{
int data;
int pos;
}Array;
void QuickSort(Array *array,int left,int right)//结构体的快排序
{
int point=array[left].data;
int Ppos=array[left].pos;
int i=left;
int j=right;
int t=0;
if(i>j)
{
return ;
}
while(i!=j)
{
while(array[j].data>=point&&i<j)
{
j--;
}
while(array[i].data<=point&&i<j)
{
i++;
}
if(i<j)
{
t=array[i].data;
array[i].data=array[j].data;
array[j].data=t;
t=array[i].pos;
array[i].pos=array[j].pos;
array[j].pos=t;
}
}
array[left].data=array[i].data;
array[left].pos=array[i].pos;
array[i].data=point;
array[i].pos=Ppos;
QuickSort(array,left,i-1);
QuickSort(array,i+1,right);
}
int* twoSum(int* nums, int numsSize, int target)
{
Array array[numsSize];
for(int i=0;i<numsSize;i++)
{
array[i].data=*(nums+i);
array[i].pos=i;
}
QuickSort(array,0,numsSize-1);
int i=0;
int j=numsSize-1;
int *res=(int *)malloc(sizeof(int )*2);
while(i<j)
{
if(array[i].data+array[j].data==target)
{
*res=array[i].pos;
*(res+1)=array[j].pos;
break;
}
if(array[i].data+array[j].data>target)
{
j--;
}
if(array[i].data+array[j].data==target)
{
*res=array[i].pos;
*(res+1)=array[j].pos;
break;
}
if(array[i].data+array[j].data<target)
{
i++;
}
}
return res;
}
最后希望如果我有什么问题大家能指正
谢谢