2020年9月23日学习笔记
代码实践:
“局部反转+整体反转”完成原地反转实践题两道:
题目1:
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof
解答1:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
string reverseLeftWords(string, int);
int main()
{
//先输入字符串,再输入待转移的字符个数k
string s;
int k;
cin>>s>>k;
//输出结果
cout << reverseLeftWords(s,k)<< endl;
return 0;
}
string reverseLeftWords(string s, int n)
{
reverse(s.begin(), s.begin() + n);
reverse(s.begin() + n, s.end());
reverse(s.begin(), s.end());
return s;
}
题目2:
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/rotate-array/
解答2:
#include <iostream>
#include <vector>
using namespace std;
void rotate(vector<int>&, int);
int main()
{
//先输入数组元素个数n,再输入数组,最后输入向右移动的位数k
vector<int> nums;
int n,k,tmp;
cin>>n;
while (n--)
{
cin >> tmp;
nums.push_back(tmp);
}
cin >> k;
rotate(nums,k);
//反向输出数组
cout << '['<<nums.back();
nums.pop_back();
while (!nums.empty())
{
cout << ','<<nums.back();
nums.pop_back();
}
cout << ']';
return 0;
}
void rotate(vector<int>& nums, int k)
{
//k有可能大于数组长度n,相当于向右移动k%n个位置
int n = nums.size();
int kk = k % n;
//运用reverse函数进行两次局部反转,整体反转通过输出结果时从后往前输出来代替
reverse(nums.begin(), nums.begin() + n - kk);
reverse(nums.begin() + n - kk, nums.end());
return;
}
知识点笔记:
平衡二叉树(AVL树)
概念:
平衡二叉树是改进后的二叉排序树(二叉查找树),它的每个结点的左右子树的高度差不超过1。调整平衡后的排序树能使得查找所需的时间最短。
二叉排序树是这样一类二叉树:如果它的左子树不为空,则他左子树上的所有节点的值都小于根结点的值;同理,如果他的右子树不为空,则右子树上所有的节点值都大于它的根节点值。而且,他的左右子树都是二叉排序树。
调整为平衡二叉树的方法:
首先要知道左旋和右旋是什么。
左旋(逆时针):
右旋(顺时针):
-
LL型(由于向失去平衡的最小子树的根节点的左子树(L)的左孩子(L)中插入新节点导致不平衡)
调整方法:右旋
-
RR型(由于向失去平衡的最小子树的根节点的右子树(R)的右孩子(R)中插入新节点导致不平衡)
调整方法:左旋
-
LR型(由于向失去平衡的最小子树的根节点的左子树(L)的右孩子(R)中插入新节点导致不平衡)
调整方法:先左旋变成LL型,再右旋
-
RL型(由于向失去平衡的最小子树的根节点的右子树(R)的左孩子(L)中插入新节点导致不平衡)
调整方法:先右旋变成RR型,再左旋
(图片中有一些字母错误,不影响过程的理解)
排序算法之选择排序
-
简单选择排序
以升序为例,第一遍扫描,找出最小的元素,与序列里的第一个元素交换,此时前半部分是有序序列(只有一个元素),后半部分是无序的待排序列;再从待排序列里找出最小的元素,与待排序列的第一个元素(整个序列的第二个元素)交换,此时有序序列长度为2,如此重复下去,进行n-1次选择与交换后,最后一个元素自然是最大的,至此,排序完成。
-
堆排序
以升序为例,先将序列构造成一个大根堆,然后每次将根节点与最后一个叶子节点交换,将最后一个元素(已到达最终位置)剔除出堆,然后将新的堆的根节点下移,重新调整为大根堆,再重复上述步骤,这样操作n-1次之后,整个序列有序。
大根堆:是一个完全二叉树,它满足这样的特征:双亲结点的值一定大于他的任意一个孩子结点的值;同理,小根堆即双亲结点的值一定小于他的任意一个孩子节点的值的完全二叉树。
如何将完全二叉树调整为大根堆:用数组构建大根堆,只需将新插入的节点(放在完全二叉树的右下角)上移到正确位置:如果它的值大于双亲结点,就将它与双亲结点的值交换,如果交换后还是大于新的双亲结点,那就继续交换,直到小于双亲结点;将刚进行过交换的根节点下移到正确位置:先找出它的孩子节点中最大的值,如果小于它,则不用调整,如果大于它,则将它与较大的那个孩子节点交换,然后继续这样和新的孩子节点比较,直到不再需要调整。
开源项目组今日贡献:
在ncov-report里提交了第三个pr:在USER_LIST.md里面增加了自己的介绍文件链接