各种算法准确实现

多种排序算法

快排

//快排
void quickSort(int *array,int left,int right) {
	if (left < right) {
		int pivot = array[left];
		int low = left, high = right;
		while (low < high) {
			while (low < high && array[high] > pivot) {
				--high;
			}
			array[low] = array[high];
			++low;
			while (low < high && array[low] < pivot) {
				++low;
			}
			array[high] = array[low];
			--high;
		}
		array[low] = pivot;
		quickSort(array,left,low-1);
		quickSort(array,low+1,right);
	}

}

归并排序

void merge(int *data,int start,int end,int *result) {
	int mid = start + ((end-start)>>1);
	int l = start, r = mid + 1;
	int cur = start;
	while (l <= mid && r<=end) {
		if (data[l] <= data[r]) {
			result[cur] = data[l];
			++l;
		}
		else {
			result[cur] = data[r];
			++r;
		}
		++cur;
	}
	while (l <=mid) {
		result[cur] = data[l];
		++cur;
		++l;
	}
	while (r<=end) {
		result[cur] = data[r];
		++r;
		++cur;
	}
	for (int i = start; i <= end; ++i) {
		data[i] = result[i];

	}
}
//归并排序
void merge_sort(int *data,int start,int end,int *result) {
	if (1 == end - start) { //只有两个元素
		if (data[start] > data[end]) {
			swap(data[start],data[end]);
		}
		return;
	}
	else if (end == start)
		return;
	else {
		int mid = start + ((end - start) >> 1);
		//cout << start << " " << mid << " " << end << endl;
		merge_sort(data,start,mid,result);

		merge_sort(data,mid+1,end,result);

		merge(data,start,end,result);

	
	}

}

字符串相关

给定一个字符串,找到第一个不重复的字符 时间复杂度为 O(N) 空间复杂度为O(1)

char findFirstSoloChar(string &str) {
	vector<int> showTime(128,0);
	for (int i = 0; i < str.size();++i) {
		++showTime[str[i]];
	}
	for (int i = 0; i < str.size();++i) {
		if (showTime[str[i]] == 1) {
			cout << str[i] << endl;
			return str[i];
		}
	}

}

KMP算法 (字符串匹配)

void computerPredix(string &m, vector<int> &prdx) {
	int mlen = m.size();
	prdx[0] = 0;
	int k = 0;
	for (int i = 1; i < mlen; ++i) {
		while (k > 0 && m[k] != m[i]) {
			k = prdx[k] < 2 ? 0 : prdx[k] - 2;
		}
		if (m[i] == m[k])
			k = k + 1;
		prdx[i] = k;
	}
}

//计算mtc串在s中出现的次数
int KMP(string &s,string &mtc) {
	int slen = s.size();
	int mlen = mtc.size();
	vector<int> predix(mlen);
	computerPredix(mtc,predix);
	int midx = 0;
	int cntMtc = 0;
	for (int i = 0; i < slen;++i) {
		while (midx > 0 && mtc[midx] != s[i]) {
			midx = predix[midx];
		}
		if (mtc[midx] == s[i])
			++midx;
		if (midx == mlen) {
			++cntMtc;
			cout << "匹配" << cntMtc << "次" << endl;
			midx = 0;
		}
	}
	return cntMtc;
}

最长公共子串匹配

动态规划,子串要求是连续的,所以只有在 i== j的时候才更新 dp[i][j] = dp[i-1][j-1]+1

给定两个字符串str1和str2,输出两个字符串的最长公共子串

题目保证str1和str2的最长公共子串存在且唯一。

 string LCS(string str1, string str2) {
        // write code here
        if("" == str1 || "" == str2) return "";
        int curl=-1,curr = -1;
        int bestLen = 0,bestr = -1;
        int len1 = str1.size();
        int len2 = str2.size();
        vector<vector<int>> dp(len1,vector<int>(len2,0));
        for(int i=0;i<len1;++i){
            if(str1[i] == str2[0]) {
                dp[i][0] = 1;
                bestr = i;
                bestLen = 1; 
            }
        }
        for(int i=0;i<len2;++i){
            if(str1[0] == str2[i]) {
                dp[0][i] = 1;
                bestr = 0;
                bestLen = 1; 
            }
        }
        for(int i=1;i<len1;++i){
            for(int j=1;j<len2;++j){
                if(str1[i] == str2[j]) dp[i][j] = dp[i-1][j-1]+1;
                if(dp[i][j] > bestLen) {
                    bestr = i;
                    bestLen = dp[i][j];
                }
            }
        }
       return str1.substr(bestr+1-bestLen,bestLen);
        
        
    }

前缀树

struct PredixTree {
	int pass; //经过了几次
	int end; //以此节点为叶节点的个数
	vector<PredixTree*> subTree;
	PredixTree() :pass(0), end(0), subTree(vector<PredixTree*>(26, nullptr)) {

	}
};
class Solution {
public:
	/**
	 *
	 * @param operators string字符串vector<vector<>> the ops
	 * @return string字符串vector
	 */
	PredixTree *root;
	Solution() { root = new PredixTree(); }
	~Solution() { delete root; }
	vector<string> trieU(vector<vector<string> >& operators) {
		// write code here
		int opLen = operators.size();
		vector<string> res;
		if (opLen < 1) return res;

		for (int i = 0; i < opLen; ++i) {
			string op = operators[i][0];
			string word = operators[i][1];
			if (op == "1") {//1 添加
				addWord(root, word);
			}
			else if (op == "2") {//2 删除
				if (isInPreTree(root, word))
					delWord(root, word);
			}
			else if (op == "3") { //3 查询
				if (isInPreTree(root, word))
					res.push_back("YES");
				else
					res.push_back("NO");
			}
			else if (op == "4") {//4 以word为前缀的单词数量
				int cnt = getWordCnt(root, word);
				res.push_back(to_string(cnt));
			}
		}
		return res;
	}

	//向前缀树中添加单词
	void addWord(PredixTree* root, string &word) {
		PredixTree *rc = root;
		for (int i = 0; i < word.size(); ++i) {
			(rc->pass)++;
			if (rc->subTree[word[i] - 'a'] != nullptr) {
				rc = rc->subTree[word[i] - 'a'];
			}
			else {
				rc->subTree[word[i] - 'a'] = new PredixTree();
				rc = rc->subTree[word[i] - 'a'];
			}
		}
		(rc->pass)++;
		(rc->end)++;
	}

	//删除word
	void delWord(PredixTree* root, string &word) {
		PredixTree *rc = root;
		int n = word.size();
		int i = 0;
		for (; i < n; ++i) {
			(rc->pass)--;
			if ((rc->subTree[word[i] - 'a']->pass) == 1) {
                PredixTree *tmp = rc->subTree[word[i] - 'a'];
                rc->subTree[word[i] - 'a'] = nullptr;
				rc = tmp;
				++i;
				break;
			}
			rc = rc->subTree[word[i] - 'a'];
		}
		(rc->pass)--;
		if (rc->pass > 0) {
			rc->end--;
			return;
		}
		while (i < n) {
			PredixTree *next = rc->subTree[word[i]-'a'];
			delete rc;
			rc = next;
			++i;
		}
		if (i == n) {
			delete rc;
			return;
		}
	}
	//是否在前缀树中
	bool isInPreTree(PredixTree* root, string &word) {
		PredixTree *rc = root;
		for (int i = 0; i < word.size(); ++i) {
			if (rc->subTree[word[i] - 'a'] == nullptr) return false;
			else
				rc = rc->subTree[word[i] - 'a'];
		}
		return true;
	}
	//获得单词的数量
	int getWordCnt(PredixTree* root, string &word) {
		PredixTree *rc = root;
		for (int i = 0; i < word.size(); ++i) {
			if (rc->subTree[word[i] - 'a'] == nullptr) return 0;
			else
				rc = rc->subTree[word[i] - 'a'];
		}
		return rc->pass;
	}
};

链表

合并两个有序链表

 ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if(nullptr == l1) return l2;
        if(nullptr == l2) return l1;
        ListNode *headPre = new ListNode();
        ListNode *newHead = headPre;
        ListNode *h1 =l1,*h2 = l2;
        while(h1 != nullptr && h2 != nullptr){
            if(h1->val < h2->val){
                newHead->next = h1;
                h1 = h1->next;
            }else{
                newHead->next = h2;
                h2 = h2->next;
            }
            newHead = newHead->next;
            newHead->next = nullptr;
        }
        if(h1 != nullptr) newHead->next = h1;
        if(h2 != nullptr) newHead->next = h2;
        newHead = headPre->next;
        delete headPre;
        return newHead;
    }

反转单链表

    ListNode* reverseList(ListNode* head) {
        if(nullptr == head || nullptr == head->next)
            return head;
        ListNode *pre = nullptr;
        ListNode *cur = head;
        while(cur != nullptr){
            ListNode *tmp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
    }

反转给定区间的单链表

 ListNode* reverseBetween(ListNode* head, int left, int right) {
        if(nullptr == head || nullptr == head->next) return head;
        if(left >= right) return head;
        ListNode *leftPre = nullptr;
        ListNode *leftNode = head;
        ListNode *rightNode = nullptr;
        ListNode *rightNext = nullptr;
        int curPos = 1;
        ListNode *hc = head;
        while(hc != nullptr){
            if(curPos == (left-1)){
                leftPre = hc;
                leftNode = hc->next;
            }
            if(curPos == right){
                rightNode = hc;
                rightNext = hc->next;
                break;
            }
            hc = hc->next;
            ++curPos;
        }

        ListNode *pre = leftNode;
        ListNode *cur = leftNode->next;
        while(cur!= nullptr && cur != rightNext){
            ListNode *tmp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = tmp;
        }

        leftNode->next = rightNext;
        if(left == 1) return rightNode;
        leftPre->next = rightNode;
        return head;      
  


    }

判断链表是否是回文

如果只需要链表的前半部分,通常都用快慢指针

bool isPalindrome(ListNode* head) {
        if(nullptr == head || nullptr == head->next) return true;
        ListNode *low = head;
        ListNode *fast = head;
        stack<int> preHalf;
        while(fast && fast->next){
            preHalf.push(low->val);
            low = low->next;
            fast = fast->next->next;
        }
        if(fast && (fast->next == nullptr)) low = low->next;
        while(low){
            if(low->val != preHalf.top()) return false;
           
            low = low->next;
            preHalf.pop();
        }
        return true;
        
    }

如何判断两个链表是否相交

 

数组

一个长度为n的整型数组,数组中的每个元素的取值范围为[0,n-1],判断该数组是否有重复的数

    int findRepeatNumber(vector<int>& nums) {
        //最简单的方法 hash
        //vector<bool> isExis(nums.size(),false);
        int n = nums.size();
        if(n<1) return -1;
        //for(int i=0;i<n;++i){
        //    if(isExis[nums[i]]) return nums[i];
        //    else
        //        isExis[nums[i]] = true;
        //}
        //return -1;
        //在原数组上进行更改
        for(int i=0;i<n;++i){
            if(nums[i] == i) continue;
            else if(nums[nums[i]] == nums[i]) return nums[i];
            else
                swap(nums[i],nums[nums[i]]);
        }
        return -1;

    }

二叉树

层次遍历

    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        if(nullptr == root) return res;
        TreeNode* rc = nullptr;
        deque<TreeNode*> dq;
        dq.push_back(root);
        int counts = 1; //下一层的节点数目
        while(!dq.empty()){
            vector<int> levelE;
            int tmpC = 0;
            while(counts--){
                rc = dq.front();
                dq.pop_front();
                levelE.push_back(rc->val);
                if(nullptr != rc->left){
                    ++tmpC;
                    dq.push_back(rc->left);
                }
                if(nullptr != rc->right){
                    ++tmpC;
                    dq.push_back(rc->right);
                }
            }
            res.push_back(levelE);
            counts = tmpC;
        }
        return res;
    }

前序、中序、后序遍历(非递归)

/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 * };
 */

class Solution {
public:
    /**
     * 
     * @param root TreeNode类 the root of binary tree
     * @return int整型vector<vector<>>
     */
    vector<vector<int> > threeOrders(TreeNode* root) {
        // write code here
        vector<vector<int>> res;
        if(nullptr == root) return res;
        vector<int> ele = preOrder(root);
        res.push_back(ele);
        ele = midOrder(root);
        res.push_back(ele);
        ele = postOrder(root);
        res.push_back(ele);
        return res;
    }
    
    vector<int> preOrder(TreeNode* root){
        vector<int> res;
        //用栈
        TreeNode* rc = root;
        stack<TreeNode* > st;
        while(root || !st.empty()){
            if(root){
                res.push_back(root->val);
                if(root->right)
                    st.push(root->right);
                root = root->left;
            }else if(!st.empty()){
                root = st.top();
                res.push_back(root->val);
                st.pop();
                if(root->right)
                    st.push(root->right);
                root = root->left;
            }
        }
        return res;
    }
    vector<int> midOrder(TreeNode* root){
        vector<int> res;
        //用栈
        TreeNode* rc = root;
        stack<TreeNode*> st;
        while(rc || !st.empty()){
            while(rc){
                st.push(rc);
                rc = rc->left;
            }
            rc = st.top();
            res.push_back(rc->val);
            st.pop();
            rc = rc->right;
        }
        return res;
    }
    vector<int> postOrder(TreeNode* root){
        //用栈
        vector<int> res;
        stack<TreeNode *> st;
        TreeNode* pre = nullptr;
        TreeNode* rc = root;
        while(rc || !st.empty()){
            while(rc){
                st.push(rc);
                rc = rc->left;
            }
            rc = st.top();
            if(nullptr == rc->right || pre == rc->right){
                st.pop();
                res.push_back(rc->val);
                pre = rc;
                rc = nullptr;
            }else{
                rc = rc->right;
            }
            
        }
        return res;
        
    }
};

Morris遍历

//二叉树morris遍历 (线索二叉树)
void morris(TreeNode *head) {
	if (nullptr == head) return;
	TreeNode* cur = head;
	TreeNode* mostRight = nullptr;
	while (nullptr != cur) {
		mostRight = cur->left;
		if (nullptr != mostRight) {
			while (nullptr != mostRight->right && mostRight->right != cur) {
				mostRight = mostRight->right;
			}
			if (nullptr == mostRight->right) {
				mostRight->right = cur;
				cur = cur->left;
				continue;
			}
			else {
				mostRight->right = nullptr;
			}
		}
		cur = cur->left;
	}
}

其他

二分

再转动过的有序数组中寻找目标值

class Solution {
public:
    /**
     * 
     * @param A int整型一维数组 
     * @param n int A数组长度
     * @param target int整型 
     * @return int整型
     */
    int search(int* A, int n, int target) {
        // write code here
        if(n < 1) return -1;
        int l=0,r=n-1;
        while(l<=r){
            int mid = l+((r-l+1)>>1);
            if(A[mid] == target) return mid;
            else if(A[mid] > target){ //变小
               if(A[l] < A[r] || A[mid] < A[l] || A[l]< target){ //在一个区间
                   r = mid-1;
               }else{
                   l = mid+1;
               }
            }else{ //变大
                if(A[l] < A[r] || A[mid] > A[r] || A[r]>=target){ //在一个区间
                    l = mid+1;
                }else{
                    r = mid-1;
                }
            }
        }
        return -1;
    }
};

回溯

有重复项数字的全排列

class Solution {
public:
    vector<vector<int> > permuteUnique(vector<int> &num) {
        vector<vector<int>> res;
        int n = num.size();
        getAns(res,num,0);
        return res;
    }
    void getAns(vector<vector<int>>& res,vector<int> &num,int curPos){
        if(curPos >= num.size()){
            res.emplace_back(num);
            return;
        }
        set<int> isV;
        int curV = num[curPos];
        for(int i=curPos;i<num.size();++i){
            if(isV.find(num[i]) != isV.end()) continue; //已经交换过就不能再交换了
            isV.emplace(num[i]);
            swap(num[curPos],num[i]);
            getAns(res,num,curPos+1);
            swap(num[curPos],num[i]);
        }
        
    }
};

洗牌算法 

有一个数组,每次随机从剩下的元素中取值,直到数组为空,获得一个随机序列。 时间复杂度O(N),空间复杂度O(1)

//洗牌算法
void shuffle(vector<int> &arr) {
	int curC = arr.size();
	int del = curC-1;
	while (curC > 0) {
		int i = rand() % curC;
		cout << arr[i] << endl;
		swap(arr[i],arr[del]);
		--del;
		--curC;
	}
}

大数据题目的解题技巧

  1. 哈希函数可以把数据按照种类均匀分流。
  2. 布隆过滤器用于集合的建立与查询,可以节省大量空间。
  3. 一致性哈希解决数据服务器的负载管理问题。
  4. 利用并查集结构做岛问题的并行计算。
  5. 位图解决某一范围上数字的出现情况,并可以节省大量空间。
  6. 利用分段统计思想,进一步节省大量空间。
  7. 利用堆外排序来做多个处理单元的结果合并。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值