1、数组部分
哈希表思想:
哈希表也称为散列表,是算法终于时间和空间作出权衡的经典例子。
当一个表所有的键都是小整数时,便可以使用一个数组来实现无序的符号表,将键作为数组的索引而数组i中所存储的值就是该键所对应的键值,即key-value对应。
哈希表的思想也是这样子的,只是哈希表的键的类型更为复杂而已。
使用哈希表(散列查找)分为两步:
- 用散列函数将被查找的键转换为数组的一个索引。理想情况下,不同的键值都会转换成为不同的索引值,但是一般情况下我们会遇到多个键对应相同的索引值,这也就是所谓的散列冲突。
- 处理碰撞冲突的情况,常用得方法有两种:拉链法(链地址法)和线性探测法。
(1)拉链法(链地址法):遇到冲突时,在原地址新建一个空间,然后以链表节点的形式插入到该空间;
(2)开放地址法(开放地址散列表):该方法是指用大小为M的数组保存N的键值对,其中,M>N。这样可以通过依靠数组M中的空位解决碰撞冲突。
C++数组自动扩容(动态数组)、有序数组动态增删改
public class MyArray {
int Size=0;
int capacity=0;
int[] p=null;
public MyArray(int len)
{
p=new int[len];
capacity=len;
}
public void add(int index,int num)
{
if(index<0||index>Size)
return ;
if(Size>=capacity)
resize(p);
p[index]=num;
Size++;
}
public void update(int index,int num)
{
if(index<0||index>Size)
return ;
p[index]=num;
}
public void resize(int[] p){
int[]temp=new int[capacity];
for(int i=0;i<capacity;i++){
temp[i]=p[i];
}
capacity=2*capacity;
p=new int[capacity];
for(int i=0;i<capacity/2;i++){
p[i]=temp[i];
}
}
public void delete(int index,int num)
{
if(index<0||index>Size)
return ;
for(int i=index+1;i<capacity;i++){
p[i]=p[i+1];
}
Size--;
}
public static void main(String[] args){
MyArray ma=new MyArray(3);
ma.add(0,0);
ma.add(1,1);
ma.add(2,2);
ma.add(3,3);
}
}
实现两个有序数组合并为一个有序数组
#include<iostream>
using namespace std;
//两个有序数组进行排序,A有足够的空间容纳B,把和A融入到一起
void MergeArray(int a[], int b[], int la, int lb)//输入A和B的数组和两个长度
{
if (la <= 0 || lb <= 0)
return; //return false;或者return 0
int index=la+lb-1;
int ida = la - 1;
int idb = lb - 1;
while (index >= 0)
{
if (a[ida] > b[idb]||idb<0) //注意边界条件,当一个数组中没有元素时,也要移动
a[index--] = a[ida--];
else if (a[ida]<=b[idb]||ida<0)
a[index--] = b[idb--];
}
}
int main()
{
int a[10] = { 3, 5, 7, 10, 15 };
int b[] = { 4, 8, 16 };
MergeArray(a, b, 5, 3);
for (int i = 0; i < 3 + 5; i++)
{
cout << a[i] << endl;
}
return 0;
}
leetcode的两数之和(1)和happy Number(202)
happy number(202)
Description
Write an algorithm to determine if a number is "happy".A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.
Example:
Input: 19
Output: true
Explanation:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1escription
- Solution
class Solution {
public:
bool isHappy(int n) {
unordered_map<int,int>map_test;
while(n != 1)
{
if (map_test[n] == 0)
map_test[n]++;
else
return false;
int sum = 0;
while(n)
{
sum = sum+ pow(n%10,2);
n = n/10;
}
n = sum;
}
return true;
}
};
2、字符串部分
Trie字典树的基本概念
Trie树是一种哈希树的变种,又称字典树,单词查找树或者前缀树,用于保存大量的字符串,是一种用于快速检索的多叉树结构(如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树)。
Trie字典树主要用于存储字符串,Trie 的每个 Node 保存一个字符。用链表来描述的话,就是一个字符串就是一个链表。每个Node都保存了它的所有子节点。
// Trie.cpp : 定义控制台应用程序的入口点。
//Trie 称为字典树,单词查找树或者前缀树
#include "stdafx.h"
#include <iostream>
#include <assert.h>
using namespace std;
const int MAX_NUM = 26;
//Trie 树的结点类型
struct Node
{
bool COMPLETED ;//COMPLETED为 true时表示目前产生的一个字符串
char ch ;
struct Node * child[ MAX_NUM]; //26-tree->a, b ,c, .....z
};
//Trie 树类型
class Trie
{
public :
Trie();
~ Trie();
Node* CreateNewNode (char ch);// 创建一个新结点
void InitTrie ();//初始化 Trie树
int CharToindex (char ch);// 找到字母对应的数组下标
int Find (const char chars [], int len);// 找到长度为 len的字符串
void Insert (const char chars [], int len);// 插入长度为 len的字符串
void Delete ();//删除整棵树
private :
void DeleteTree (Node *& root);
Node* root ; //根结点
};
Trie::Trie ()
{
root = NULL ;
}
Trie::~Trie ()
{
}
Node* Trie ::CreateNewNode( char ch )//创建一个新的结点
{
Node *new_node = new Node;
new_node->ch = ch;
new_node->COMPLETED = false;
for(int i=0; i<MAX_NUM ; i++)
{
new_node->child [i] = NULL;
}
return new_node ;
}
void Trie ::InitTrie() //构建一棵空树
{
root = CreateNewNode (' ');
}
int Trie ::CharToindex( char ch )
{
return ch - 'a';
}
int Trie ::Find( const char chars[], int len )
{
if (root == NULL)
{
cout<<" 树为空!"<< endl;
return 0;
}
Node* ptr = root;
int i = 0;
while(i < len)
{
if(ptr ->child[ CharToindex(chars [i])] == NULL)
{
break;
}
ptr = ptr ->child[ CharToindex(chars [i])];
i++;
}
return (i == len) && ( ptr->COMPLETED == true);
}
void Trie ::Insert( const char chars[], int len ) //向 Trie树中插入长度为len的字符串
{
Node* ptr = root;
for(int i = 0; i < len ; i++)
{
if(ptr ->child[ CharToindex(chars [i])] == NULL)
{
ptr->child [CharToindex( chars[i ])] = CreateNewNode (chars[ i]);
}
ptr = ptr ->child[ CharToindex(chars [i])];
}
ptr->COMPLETED = true;
}
void Trie ::Delete() //利用递归删除整棵树
{
DeleteTree(root );
}
void Trie ::DeleteTree( Node *&Root )//利用递归删除整棵树 注意此处应该加上应用
{
if (Root == NULL) //递归出口
{
return;
}
for (int i=0; i<MAX_NUM ; i++)
{
if (Root ->child[ i] != NULL )
{
DeleteTree(Root ->child[ i]);
}
}
// if(Root->ch == ' ')
// {
// cout<<"zha'"<<endl;
// }
delete Root ;
Root = NULL ;
}
int _tmain (int argc, _TCHAR * argv[])
{
char *a = "ten";
char *b = "tea";
Trie trie ;
trie.InitTrie ();
trie.Insert (a, 3);
trie.Insert (b, 3);
cout<<trie .Find( a,3)<<endl ;
trie.Delete ();
cout<<trie .Find( b,3)<<endl ;
system("pause" );
return 0;
}
2.2实现朴素的字符串匹配算法
//在主串s中找子串t,若找到返回字串在主串中的索引;若没找到返回-1
#include <iostream>
#include <string>
using namespace std;
int Index(string s, string t){
int lens = s.length();//计算串s、t的长度
int lent = t.length();
int i = 0;
int j = 0;
while (i < lens&&j < lent){//如果i、j都各自小于lens和lent
if (t[j] == s[i]){//如果子串的t[j]和主串的s[i]相等
++i;//各自索引都自增
++j;
}
else{//否则,主串的索引比刚开始后移一个;子串的索引变为0
i = i - j + 1;
j = 0;
}
}
if (j == lent){//如果最j和lent的大小一样,证明找到了,返回子串在主串中的索引
return i - lent;
}
else{//否则返回-1
return -1;
}
}
int main(){
string s = "goodgoogle";
string t = "google";
int pos = Index(s, t);
if (pos != -1){
cout << "find " << t << " at the index " << pos << " of " << s << endl;
}
else{
cout << "can't find " << t << " in " << s << endl;
}
return 0;
}
本文参考及学习资料:
【1】https://github.com/Sly-Guo/learngit/blob/master/数据结构编程学习/
【2】哈希表设计思想及实现:https://songwell1024.github.io/2018/07/01/HashTable/
【3】数据结构与算法(十一)Trie字典树https://blog.csdn.net/johnny901114/article/details/80711441
【4】https://blog.csdn.net/sinat_36053757/article/details/71023766