记录刷题时的小知识

for(int i=startx;i<n-offset;i++)
{
    res[startx][i] = cout++;
}
在for循环时创建的i,在for循环结束后也销毁。

虚拟头节点的指向问题:

struct ListNode* swapPairs(struct ListNode* head) {
    if (head == NULL) { // 空链表直接返回空
        return NULL;
    }
    struct ListNode* virnode = (struct ListNode*)malloc(sizeof(struct ListNode)); // 虚拟头结点
    virnode->val = 0;
    virnode->next = head;
    struct ListNode* cur = virnode; // 遍历链表的指针cur 
    int i = 1;
    while (cur->next&&cur->next->next) { // 只要cur->next不空或者不是一个结点的情况则继续遍历
        struct ListNode* first = cur->next; // 指向第一个结点的指针
        struct ListNode* second = cur->next->next; // 指向第二个结点的指针
        cur->next = second; // 这里第一次遍历时会直接改变虚拟头结点的next的指向,它会指向链表新的第一个结点
        cur = second; // 更新cur指针的位置使其指向第二个结点,同时这一步也使cur不再指向虚拟头结点,
                      //从而后续的遍历不会影响虚拟头结点next指向链表的第一个结点 
        struct ListNode* newnext = second->next; // 第二个节点后面的结点的地址
        
        second->next = first; // 这里是两个结点进行交换的操作
        first->next = newnext; // 将交换的后结点链接回原来的第二个结点的后续结点

        cur = first; // 更新cur指针到新的遍历位置 
    } // 重复这个过程,这里可以通过上面图示自己走读一遍代码,标记好指针的位置即可
    head = virnode->next; 
    return head;
}

链表结构是内存内部的一种存储方式,可以把链表结构想象成是一串节点,由若干个节点穿成一串的数据结构。每个节点都有两个区域:数据域和指针域。指针域指向下一个节点的地址。 链表节点的指针域和数据域都会占用内存。每个链表节点都包含两个部分:数据域和指针域。数据域存储节点的数据,指针域存储下一个节点的地址。因此,每个链表节点的内存占用量取决于数据域和指针域的大小。在C语言中,指针通常占用4个字节或8个字节,而数据域的大小则取决于数据类型。例如,如果数据域是一个整数,则占用4个字节;如果数据域是一个字符,则占用1个字节。总的来说,链表节点的内存占用量取决于数据域和指针域的大小,以及指针的大小。

数组是在内存中是连续分布的,但是链表在内存中可不是连续分布的。

链表无头节点就要单独对头节点处理,因为非头节点处理没有对第一个节点处理,而是接续对下一头节点处理。要判断头节点和下一节点是否为空,防止处理错误。

哈希表

哈希表是根据关键码的值而直接进行访问的数据结构。

哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素。

当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。

数组法需要知道问题占用空间大小,而且如果元素很少,而哈希值太大会造成内存空间的浪费,set不需要,可以继续插入。

将学生姓名映射到哈希表上就涉及到了hash function ,也就是哈希函数。 

通过hashCode把名字转化为数值,一般hashcode是通过特定编码方式,可以将其他数据格式转化为不同的数值,这样就把学生名字映射为哈希表上的索引数字了。

哈希冲突解决办法:

1、链表式解决

        遇到冲突的时候,把数据写到next的位置。

2、开放地址

a 线性探测法

如果遇到冲突,新位置=原始位置+i(i是查找的次数)

b 平方探测(二次方探测)

如果遇到冲突,新位置=原始位置 + i平方(i为查找的次数)

c 双哈希

要设置第二个哈希的函数,例如hash2(key) = R - (key mod R)

R要取比数组尺寸小的质数。

如果遇到冲突,新位置=旧位置 + i*hash2(i为搜索次数)

std::unordered_set底层实现是哈希表,无序,查找高效

std::set和std::multiset底层实现是红黑树,是一种平衡二叉搜索树,key值有序,但key不能修改。std::multiset数值可以重复。

std::unordered_map底层实现是哈希表,std::map和std::multimap底层实现是红黑树。只有std::multimap的值可重复。

虽然std::set、std::multiset 的底层实现是红黑树,不是哈希表,std::set、std::multiset 使用红黑树来索引和存储,不过给我们的使用方式,还是哈希法的使用方式,即key和value。所以使用这些数据结构来解决映射问题的方法,我们依然称之为哈希法。 map也是一样的道理。

使用数组来做哈希的题目,是因为题目都限制了数值的大小。

而这道题目没有限制数值的大小,就无法使用数组来做哈希表了。

n位数的每一位平方和代码:

int getsum(int n)
    {
        int sum=0;
        while(n)
        {
            sum+= (n%10)*(n%10);
            n /= 10;
        }
        return sum;
    }

在C++中,使用大括号 {} 可以用于初始化一个容器,比如 std::vector 或者一个 std::array。这种语法被称为初始化列表(initializer list)。

在这个特定的情况下,return {iter->second, i}; 表示创建一个包含两个元素的 std::vector<int>,其中第一个元素是 iter->second,第二个元素是 i。这样的语法在C++11及以后的标准中是合法的。

而在C++中,使用方括号 [] 不会创建一个数组或者向量,而是用于访问数组或者向量的元素。所以 return [iter->second, i]; 是不合法的C++语法。

总之,return {iter->second, i}; 是用于返回一个包含两个整数的向量,而不是访问数组或向量元素的值。

sort方法

例如,对于输入的向量 nums = {3, -2, 1, -5, 4}, 使用 nums.sort() 函数排序后,得到的结果是 { -5, -2, 1, 3, 4 },即负数在前,正数在后,而且每个数按照绝对值的大小进行排序。

使用map的空间消耗要比数组大一些,因为map要维护红黑树或者符号表,而且还要做哈希函数的运算。所以有时候数组更加简单直接有效 

std::map 和std::multimap 的key也是有序的

合法:for(int i=0,  j=(s.size()-1);i < s.size()/2;i++,j--)
不合法:for(int i=0,  int j=(s.size()-1);i < s.size()/2;i++,j--)

 在 C++ 中,当你在 for 循环的初始化部分声明变量时,你不需要再次指定变量的类型,因为已经在声明的时候指定了。因此,在循环初始化的部分,你只需要写变量名和初始化值即可,不需要再次指定类型。这就是为什么 int j=(s.size()-1) 是合法的,而 int i=0, int j=(s.size()-1) 是不合法的。

一般库函数是左闭右开规则

栈与队列

st.pop()直接弹出栈顶元素,不能拿来比较,比较用top()函数。

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<long long> st;
        for(int i=0;i<tokens.size();i++)
        {
            if(tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/")
            {
                long long num1=st.top();
                st.pop();
                long long num2=st.top();
                st.pop();
                if(tokens[i] == "+") st.push(num1+num2);
                if(tokens[i] == "-") st.push(num2-num1);
                if(tokens[i] == "*") st.push(num1*num2);
                if(tokens[i] == "/") st.push(num2/num1);
                
            }
            else 
            {
                st.push(stoll(tokens[i]));
            }
        }
        int result = st.top();
        st.pop();
        return result;
    }
};

if(tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/")里tokens的每个元素是vector<string>类型的,因此用""而不用字符型''

静态数组 int array[100] = {1}; //定义了数组array,并将数组第一个元素初始化为1,后面99个元素初始化为0;

数组初始化列表中的元素个数小于指定的数组长度时,不足的元素补以默认值。

注意如果在定义结构体变量的时候没有初始化,那么后面就不能全部一起初始化了;意思就

是:

/这样是可以的,在定义变量的时候就初始化了;
struct book s1={//对结构体初始化 
        "guojiajiaoyun",//author为字符数组 
          "yuwen",//title为字符串 
          22.5
    };
/这种就不行了,在定义变量之后,若再要对变量的成员赋值,那么只能单个赋值了;
struct book s1;
    s1={ 
         "guojiajiaoyun",//author为字符数组 
          "yuwen",//title为字符串 
          22.5  
};//这样就是不行的,只能在定义的时候初始化才能全部赋值,之后就不能再全体赋值了,只能单个赋值;


只能;


s1.title = "yuwen";........//单个赋值;

数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragmapack指定的数值和这个数据成员自身长度中,比较小的那个进行。 

在C++标准库中,pop()方法不是一个通用的数据结构方法。不同的数据结构有各自的特定方法来移除元素。这里是几个常见的数据结构及其对应的移除方法:

  1. std::deque(双端队列):

    • pop_front(): 移除前端的元素。
    • pop_back(): 移除后端的元素。
  2. std::stack(栈):

    • pop(): 移除栈顶元素。
  3. std::queue(队列):

    • pop(): 移除队列前端的元素。
  4. std::priority_queue(优先队列):

    • pop(): 移除队列顶端元素(最大或最小,取决于优先级定义)。

 c语言struct结构体强制类型转换_c语言结构体强制类型转换-CSDN博客

C语言结构体(struct)最全的讲解(万字干货) - 知乎 (zhihu.com)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值