1、此为使用c++形式生成固定数量的随机数
使用时间作为种子 srand()函数定义种子给rand()函数生成随机数使用。平时很少用。不过有个问题,这样生成的随机数平均短时间内连续生成的话,每一轮会比之前的大。程序运行的时间间隔可以把握下。根据使用特性选择合适的容器存储就行
2、练习
使用C++也是因为想练习封装和类的使用,可以多尝试
#include <cstdlib>
#include <iostream>
#include <ctime>
#include <set>
using namespace std;
// 第一步:设定随机整数的个数
// 第二步:生成随机数并且存入容器中
// 第三步:遍历容器输出(可使用set容器)
class Srand_numbers
{
private:
set<int> _randnumber;
int _numbers; //随机数的个数
int _tempnumbers = 0; //暂存随机数
public:
Srand_numbers(int nums)
:_numbers(nums)
,_randnumber()
{
}
void product_rand_number(int numbers);
void store_numbers(int tempnum);
void display_numbers();
};
void Srand_numbers::product_rand_number(int numbers)
{
//生产随机数并存储
srand((unsigned int)time(NULL));
while(numbers -->0)
{
_tempnumbers = rand()%500;
store_numbers(_tempnumbers);
}
}
void Srand_numbers::store_numbers(int tempnum)
{
_randnumber.insert(tempnum);
}
void Srand_numbers::display_numbers()
{
set<int>::iterator it;
for(it = _randnumber.begin(); it != _randnumber.end(); ++it)
{
cout << *it << endl;
}
}
int main() {
int inumbers = 0;
cin >>inumbers ;
Srand_numbers srand1(inumbers);
srand1.product_rand_number(inumbers);
srand1.display_numbers();
}
3、一个循环解决水瓶子换水的问题
总体思路就是三个瓶子换一瓶水(3个空瓶子换一瓶水,这个题目语言和生活尝试的认知还是比较有趣的,正常情况,我是把瓶子默认是空瓶,带水的就是一瓶水),空瓶子继续换,手里空瓶子=2时,可以借老板一个,3瓶换一瓶水
#include <cstdlib>
#include <iostream>
using namespace std;
void exchange_num(int emptynums)
{
if(emptynums ==0)
{
exit(0);
}
int totle_nums = 0;
while(emptynums>=1 && emptynums <= 100 )
{
int _avlable_bottles = emptynums % 3; //空瓶子数目最大兑换量之后,剩下的数量
int water_bottle = (emptynums - _avlable_bottles) /3; //计算出有多少个3空瓶
if(_avlable_bottles ==1 && water_bottle == 0) //输入的为1瓶时
{
cout << totle_nums << endl;
break; //输入的为1瓶,这里需要添加一个退出循环的方式,不然程序一直运行
}
if(water_bottle != 0) //输入的大于2瓶时
{
totle_nums += water_bottle;
int temp_empty = water_bottle + _avlable_bottles;
emptynums = temp_empty;
if(emptynums == 2)
{
emptynums +=1;
}
continue;
}
}
}
int main() {
int a = 0;
while(cin >> a)
{
exchange_num(a);
}
}
// 64 位输出请用 printf("%lld")
4、检查链表中存在的环问题(查找环的入口结点)
快慢指针,一般使用快指针走两步,慢指针走一步。所以第一次相遇,快指针走了慢指针的2倍。但是,不能确定快慢指针一共走了多少个环,相遇的结点是环内哪一个结点,有可能不是入口值。
参考leetcode大佬的解释,LCR 022. 环形链表 II - 力扣(LeetCode)
struct ListNode{
ListNode *next;
int value;
ListNode(int x) : val(x), next(NULL) {} //执行一个,,构造函数,初始化数据成员
}
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(head==NULL || head->next ==NULL){
return NULL; //此处判断,链表是否为空,或者只有一个结点,是则结束就好
}
ListNode *slow, *fast;
slow = head,fast = head; //使用快慢指针,一定要初始化,否则容易产生野指针的问题
while(head->next != NULL)
{
slow= slow->next;
fast= fast->next->next; //总体结构,使用快慢指针,快指针走两步,满指针走一步,有时候对这个走动感觉比较抽象,不像数组可以直接加减下标访问。这里使用指针的next
if(slow == fast)
{
break ; //此处表示有环,快慢指针相遇,但是此处不一定是环的入口,想找到入口,还需要调整
}
}
fast = head;
while(fast != slow)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
};
5、原地反转链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *curr = head;
ListNode *prev = nullptr;
while(curr) //当curr指向的内存空间为null/nullptr退出循环
{
ListNode * pnext = curr->next; //记住链表当前结点的下一个结点,防止断链
curr->next = prev;
prev = curr;
curr = pnext;
}
return prev; //最后的prev就是新的头节点
}
};
记录一下这个思路吧,总是感觉这个反转有点反正常思维;先将head—>next 指向的地址当作 qq 。
1、首先链表的一个特性,如果我们直接把第一个结点断开后,head->next 指向的是prev,,这时后面的qq以及之后的链表也就失连了。因为head->next 指向的不是不再是qq,没有东西可以找到qq了。
2、所以可以用一个其其他名字的指针pnext,指向头指针原来指向的位置;这样head指向别处,但是pnext就是qq的地址,我们仍然可以找到后面的链表
3、之后再将当前这个已经转向的结点设置为prev,这样每次循环,这个结点都是是原先正向链表结点的前一个(比较抽象的描述,因为链表地址本来就是不连续,这里只是一个标志),再将正序链表设定为curr,就可以循环执行,直到curr = nullptr, 也就是前面的反转完了。返回prev就可以了。这样原先的尾结点就变头节点了