指针

双指针思想的题型总结

旧巷老猫 提交于 2020-02-26 14:52:50
将刷题过程中陆续碰到的双指针题型进行一下汇总总结 题目1:不重复打印排序数组中相加和为给定值的所有二元组 题目描述 给定排序数组arr和整数k,不重复打印arr中所有相加和为k的不降序二元组 例如, arr = [-8, -4, -3, 0, 1, 2, 4, 5, 8, 9], k = 10,打印结果为: 1, 9 2, 8 [要求] 时间复杂度为 O(n) O ( n ),空间复杂度为 O(1) O ( 1 ) 输入描述: 第一行有两个整数n, k接下来一行有n个整数表示数组内的元素 输出描述: 输出若干行,每行两个整数表示答案按二元组从小到大的顺序输出(二元组大小比较方式为每个依次比较二元组内每个数) import java.util.*; public class Main{ public static void main(String[] args){ Scanner in=new Scanner(System.in); int n=in.nextInt(); int k=in.nextInt(); int[]a=new int[n]; for(int i=0;i<n;i++){ a[i]=in.nextInt(); } printDouble(a,k); } public static void printDouble(int []a,int k){ if(a

引用与指针的区别

萝らか妹 提交于 2020-02-26 13:42:03
目录 1 引用的概念 2 指针的概念 3 定义引用 4 引用和指针的区别 1 引用的概念 引用就是变量的别名,对引用的操作等价于对变量的操作,不会给引用分内存空间,引用和被引用的变量共享一块内存空间。 一个变量可以有多个引用,一个引用只能对应一个变量(一个引用不能是多个变量的别名)。 2 指针的概念 指针是“指向”另外一种类型的符合类型。指针可以实现对对象的间接访问。 3 定义引用 数据类型 &引用名 = 变量名; 注意: 1)在定义引用的时候一定要初始化 2)一个引用只能是一个变量的别名,不能是多个变量的别名 &什么时候是取地址,什么时候是引用? &前有数据类型就是引用, &前没有数据类型就是取地址 4 引用和指针的区别 区别如下: 1)指针占4个字节内存空间,引用不占内存,引用的和被引用的变量共用同一块内存空间 2)指针可以改向,引用一旦初始化完成,不能变成别的变量的引用 3)指针可以不初始化,引用一定要初始化 4)指针的运算只是移动一个数据类型的地址,引用的运算就是变量的运算 5)可以有void*型指针,不能有void型的引用 6)有数组指针,函数指针,不能有数组引用,和函数引用 7)常引用可以是常量的别名,指针只能是字符串常量的地址,不能定义成其他常量的地址。 8)可以定义多级指针,但不能这样定义: 数据类型 && 引用名 = 变量名; 引用也可以有别名

数据结构与算法:链表

谁都会走 提交于 2020-02-26 10:29:37
一、链表和数组的区别 链表与数组相似,但链表是一种比数组稍微复杂的数据结构。数组需要一块连续的内存空间来存储数据,对内存的要求比较高,而链表则不需要,它通过「指针」将不连续的内存块串联起来。如果要申请一个 100MB 大小的数组和链表,当内存中没有连续的,或者没有足够大小的空间时,数组便会申请失败,而链表不会。 链表有很多种结构,常见的有: 单链表 、 双向链表 、 循环链表 。 二、单向链表 链表通过指针将不连续的内存块串联在一起使用,我们把其中的内存块称为「结点」,而为了将所有的结点串起来,链表中的结点除了存储数据之外,还会用指针记录链表结点的下一个结点的地址,我们把这个记录下一个结点的地址的指针叫做「后继指针next」,整个单链表如下图所示。 其中第一个结点和最后一个结点是比较特殊的,通常分别把它们称为「头结点」和「尾结点」。头结点用来记录链表的基地址,有了它就能遍历得到整个链表。尾结点并不指向任何结点,而是指向空地址 null ,表示链表上的最后一个结点。 与数组不同,链表的插入和删除操作并不需要大量的数据搬移,它只需要考虑相邻结点的指针改变,对应的时间复杂度为 O(1) 。同样,链表的访问元素操作也没有数组那样直接用首地址和下标通过寻址公式直接得到对应的内存地址,链表需要通过从指针一个一个结点地遍历,直到找到相应的结点。因此链表的随机访问时间复杂度为 O(n) 。 三

28-指针的定义和初始化

牧云@^-^@ 提交于 2020-02-26 05:28:10
本节知识点: 1、指针变量 2、定义一个指针变量 3、指针变量的引用 4、指针变量的初始化方法 5、使用*获取指针对应存储区域的内容 ---------------------------------------------------------------------------------------------------- 1、指针变量    在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。   因此,一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。 注意,严格意义上讲:    指针 是一个地址, 是一个常量。    指针变量 是存放一个地址, 是一个变量。 指针变量用于存放指针(地址)。 对比整型数据理解:int a = 10;   10 是一个整型数据, 是一个常量   整型变量a是存放整型数据的,是一个变量。 图中:变量i_pointer 就是一个指针变量,查看k = i + j; 的存储过程 2、定义一个指针变量 对指针变量的定义包括3个内容:   (1) 指针类型说明,即定义变量为一个指针变量   (2) 指针变量名   (3) 变量值(指针) 一般形式为: 类型说明符 *变量名 可以理解为 (类型说明符 *)变量名   其中, 这里的*只具有象征意义,仅表示这是一个指针变量 ,变量名即为定义的指针变量的名称

C++编程关键路径(一)

懵懂的女人 提交于 2020-02-26 03:05:13
最近看了这本由中国水利水电出版社出版的这本书,作者是梁永军,感觉里面的东西对我个人来说挺有用的,所以总结一下,也算是自己复习一下 第一章:C语言关键知识 1、关于内存: (1)栈:是用于那些在编译期间就能确定存储大小的变量的存储区,在函数作用域内创建,离开作用域后自动销毁。通常存储的是局部变量、函数参数等。存储区域一般是相邻的。 (2)堆:是用于那些在编译期间不确定存储大小的变量的存储区,存储空间一般是不连续的,由malloc(new)和free(delete)来申请和释放内存, (3)全局(静态存储区):在编译期间就能确定变量占用内存的大小,一般是全局变量和静态变量。 (4)常量存储区:存放的是常量,程序运行期间,全局可见,不允许被修改。 变量分为左值和右值,对于:char* p=”hello world”;中,左值是局部指针变量p,存储于函数栈上,右值是字符串常量”hello world”,存储于常量存储区。 2、函数的参数传值和传址 参数传值:把实参的值复制到函数运行时分配给函数的参数存储区中,函数不会访问调用函数的实参,被调用函数处理的是实参在本地的拷贝,这些拷贝值存储在函数的栈中。 参数传址:把实参的地址(指针或引用)传入函数,被调用的函数直接操作的是变量的地址,目的有两个:一个是改变传入的变量的值,一个是提高效率,减少参数传值过程中需要的复制过程。 在实际开发中

c语言之指针

ε祈祈猫儿з 提交于 2020-02-26 02:58:35
指针就是用来存放地址。 &(取地址) 表示取出这个变量的地址符号, *(解引用) 指针说明符号,取地址里面的值 。 指针理解: int A=12;int *p=&A;把12存在变量 A空间 的 地址上 。把A的空间里面地址存在p指针上。 指针格式:指针虽然指针存放地址,但是也有类型。 int a = 5; int * p = &a; #include<stdio.h> #include<windows.h> int main() { int a = 5; int* p = &a; printf("这是指针的值:%d\n",*p); printf("这是指针的地址:%p\n", p); return 0; } 指针基础 数组和指针的关系;一维数组的数组名就是一个指针。 #include<stdio.h> #include<windows.h> int main() { int array[5] = { 1,2,3,4,5 }; int* p = array; for (int i = 0; i < 5;i++) { printf("直接使用指针作为数组名:%d\n",p[i]); } system("pause"); return 0; } 指针数组关系 悬空指针: 使用完之后(一般就是free释放空间之后)没有及时赋值为NULL的指针就是悬空指针。 野指针:

C++野指针的存在方式和误区

♀尐吖头ヾ 提交于 2020-02-26 02:40:48
1. char* x;这样的一定是野指针,指针声明时要直接初始化!或者置null也行! 2. 1 int main() 2 { 3 char *x=new char; 4 delete x; 5 cout<<*x; 6 getchar(); 7 return 0; 8 } delete x;之后,x就是一个野指针。 1 int main() 2 { 3 char *x=new char[10]; 4 cout<<*x; 5 strcpy(x,"dqwdqw"); 6 delete []x; 7 cout<<x; 8 getchar(); 9 return 0; 10 } 这段代码是能运行的,但delete[]x;之后,x就成为了一个野指针,输出的结果是未定义的。这里我们应该加上: x=nullptr; 或者malloc之后free掉的指针,也是上面的情况,一定要把指针置null。 3. 函数参数为二级指针&p,将p指向了函数中的临时变量。函数调用完毕后,p这个指针就变为了野指针。 1 int f(char** x){ 2 char p=97; //'a' 3 *x=&p; 4 } 5 int main() 6 { 7 char a=65; //'A' 8 char *x=&a; 9 f(&x); 10 cout<<*x; 11 getchar(); 12 return 0; 13

[LeetCode] [链表] 相关技巧总结

感情迁移 提交于 2020-02-25 22:47:44
刷完了LeetCode链表相关的经典题目,总结一下用到的技巧: 技巧 哑节点--哑节点可以将很多特殊case(比如:NULL或者单节点问题)转化为一般case进行统一处理,这样代码实现更加简洁,优雅 两个指针--链表相关的题目一般都需要用到两个指针:prev指针和cur指针 头插法--主要用于reverse链表 前后指针/slow fast指针--用于检测链表是否存在环 来源: https://www.cnblogs.com/wengle520/p/12316596.html

命令行参数————(int argc,char *argv[])

寵の児 提交于 2020-02-25 21:38:22
命令行参数————(int argc,char *argv[]) C 编译器运行 main() 没有参数或者有两个参数(一些实现允许 main() 有更多参数,属于对标准的扩张) 。 main() 函数有两个参数时,第一个参数是命令行中的字符串数量。过去,这个 int 类型的参数被称为 argc ( 表示参数计数 : arguemnet count )。系统用空格表示一个字符串的结束和下一个字符串的开始。 命令行字符串存储在内存中,而字符串的地址存储在指针数组中。而该数组的地址则被存储在 main() 的第二个参数中。按照惯例,这个指向指针的指针称为 argv ( 表示参数值 [ arguement value ])。 main() 函数中的形式参数与其它带形参的函数相同。许多程序员用不同的形式声明 argv : int main ( int argc , char * * argv ) char **argv 与 char *argv[] 等价,也就是说, argv 是一个指向指针的指针,它所指向的指针指向 char 。因此,即使在原始定义中, argv 也是指向指针的指针。两种形式都可以使用,但我们认为第一种形式更清楚的表明 argv 表示一系列字符串。 来源: CSDN 作者: Masschusates 链接: https://blog.csdn.net/qq

剑指offer学习笔记 链表中倒数第k个节点

a 夏天 提交于 2020-02-25 19:28:31
鲁棒是英文Robust的音译,有时也翻译成健壮性。鲁棒性指程序能够判断输入是否合乎规范要求,并对不符合要求的输入予以合适的处理。 容错性是鲁棒性的一个重要体现,不鲁棒的软件在发生异常事件时,如用户输入错误的用户名、试图打开的文件不存在或者网络不能连接,会出现不可预见的诡异行为,或者干脆整个软件崩溃。 提高代码的鲁棒性的有效途径是进行预防性编程,预防性编程是一种编程习惯,指预见在什么地方可能会出现问题,并为这些可能出现的问题制定处理方式。如当试图打开的文件不存在时,可以提示用户检查文件名和路径。 面试时最简单实用的防御性编程是在函数入口对用户的输入是否符合要求进行验证。如输入的是一个指针,那么空指针时怎样进行处理。 面试题22:链表中倒数第k个节点。输入一个链表,输出该链表中倒数第k个节点。为符合大多数人习惯,本题从1开始计数,即链表的尾节点是倒数第一个节点。链表节点定义如下: struct ListNode { int m_nValue ; ListNode * m_pNext ; } ; 为了得到倒数第k个节点,很自然的想法是先走到链表的尾端,再从尾端回溯k步。可是本题中的链表是单向链表,只有从前向后的指针而没有从后向前的指针,这种思路行不通。 假设整个链表有n个节点,那么倒数第k个节点就是从头结点开始的第n-k+1个节点(头节点为第一个节点)。因此,如果我们能够得到链表的长度n