C++ 简单算法题

 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就可以了。这样原先的尾结点就变头节点了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值