数组
创建一维数组:
int *ans=(int*)malloc(sizeof(int)*numsSize)
创建二维数组
// 第一步 分配内存给二维数组
int** ans=(int**)malloc(sizeof(int*)*n);
// 第二步 分配内存给一维数组
for(int i=0;i<n;i++){
ans[i]=(int*)malloc(sizeof(int)*n);
}
二分查找
int search(int* nums, int numsSize, int target){
int l=0,r=numsSize-1;
while(l<=r){
int mid=(l+r)/2;
if(nums[mid]>target){
r=mid-1;
}else if(nums[mid]<target){
l=mid+1;
}else{
return mid;
}
}
return -1;
}
移除元素
// 快指针遍历整个数组,不等于移除元素时就赋值给慢指针.
int removeElement(int* nums, int numsSize, int val){
int slow=0;
for(int fast=0;fast<numsSize;fast++){
if(nums[fast]!=val){
nums[slow++]=nums[fast];
}
}
return slow;
}
有序数组的平方和
int* sortedSquares(int* nums, int numsSize, int* returnSize){
*returnSize=numsSize;
// 创建新的数组
int*ans=(int*)malloc(sizeof(int)*numsSize);
// 逆向赋值给新数组
int k=numsSize-1;
// 双指针一头一尾
int i=0,j=numsSize-1;
// 比较两侧的平方和,将平方和大的赋值给新数组,并移动指针
for(int index=numsSize-1;index>=0;index--){
int leftSquare=nums[i]*nums[i];
int rightSquare=nums[j]*nums[j];
if(leftSquare<rightSquare){
ans[k--]=rightSquare;
j--;
}else{
ans[k--]=leftSquare;
i++;
}
}
return ans;
}
最短子数组
int minSubArrayLen(int target, int* nums, int numsSize){
int res=INT_MAX;
int i=0; //起点
int sum=0; //片段和
for(int j=0;j<numsSize;j++){ //终点
sum+=nums[j];
while(sum>=target){
int sublen=j-i+1; //截取长度
res=res<sublen?res:sublen; //更新最小长度
sum-=nums[i++]; //移动起点,相当于窗口往前移动
}
}
return res==INT_MAX?0:res;
}
蛇形矩阵
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes){
*returnSize=n;
*returnColumnSizes=(int*)malloc(sizeof(int)*n);
// 创建二维数组 ans
// 第一步 分配内存给二维数组
int** ans=(int**)malloc(sizeof(int*) * n);
// 第二步 分配内存给一维数组
for(int i=0;i<n;i++){
ans[i]=(int*)malloc(sizeof(int) *n);
(*returnColumnSizes)[i]=n;
}
int cnt=1; //填入的数字
int loop=n/2; //循环圈数
int offset=1; //边界
int startx=0,starty=0; //第一圈从(0,0)开始填入
while(loop-->0){
int i=startx,j=starty;
// 上方从左到右
for(j=starty;j<n-offset;j++){
ans[startx][j]=cnt++;
}
// 右侧从上到下
for(i=startx;i<n-offset;i++){
ans[i][j]=cnt++;
}
// 下侧从右到左
for(;j>starty;j--){
ans[i][j]=cnt++;
}
// 左侧从下到上
for(;i>startx;i--){
ans[i][j]=cnt++;
}
// 下一圈从(1,1)开始填
startx++;
starty++;
offset++;
}
// 中间单独填
if(n%2){
ans[n/2][n/2]=cnt;
}
return ans;
}
链表
设计链表
// 1.链表定义
typedef struct MyLinkedList{
int val;
struct MyLinkedList*next;
} MyLinkedList;
// 2.链表初始化
MyLinkedList* myLinkedListCreate() {
// 虚拟头节点
MyLinkedList*head=(MyLinkedList*)malloc(sizeof(MyLinkedList));
head->next=NULL;
return head;
}
// 3.获取下标对应的节点值
int myLinkedListGet(MyLinkedList* obj, int index) {
MyLinkedList*cur=obj->next; //从虚拟节点的下一个节点(头节点)开始遍历
for(int i=0;cur!=NULL;i++){
if(i==index){
return cur->val;
}else{
cur=cur->next;
}
}
return -1;
}
// 4.添加到头节点
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
// 为要添加的节点分配内存空间
MyLinkedList* cur=(MyLinkedList*)malloc(sizeof(MyLinkedList));
cur->val=val;
// 连接 obj--cur--head
cur->next=obj->next;
obj->next=cur;
}
// 5.添加到尾部
// cur遍历到最后一个节点
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
MyLinkedList* cur=obj;
while(cur->next!=NULL){
cur=cur->next;
}
MyLinkedList* tail=(MyLinkedList*)malloc(sizeof(MyLinkedList));
tail->val=val;
// cur--tail--null
tail->next=NULL;
cur->next=tail;
}
// 6.在下标为index的节点前插入节点
// 先创建cur,定位到目标节点的前一个节点,插入时的位置关系为 cur--addNode--cur->next
void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
// 特判,添加到头节点
if(index==0){
myLinkedListAddAtHead(obj,val);
return;
}
//遍历节点,用于定位到目标节点的前一个节点
MyLinkedList* cur=(MyLinkedList*)malloc(sizeof(MyLinkedList));
cur=obj->next;
for(int i=1;cur!=NULL;i++){
if(i==index){
MyLinkedList* addNode=(MyLinkedList*)malloc(sizeof(MyLinkedList));
addNode->val=val;
addNode->next=cur->next;
cur->next=addNode;
}else{
cur=cur->next;
}
}
}
// 7.删除下标为index的节点
// 特判删除头节点 obj->next=obj->next->next
// 遍历到目标节点的前一个节点cur,cur->next=cur->next->next,删除前要判断节点是否为空
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
//特判,删除头节点
if(index==0){
MyLinkedList* temp=obj->next; //原来的头节点
if(temp!=NULL){
obj->next=obj->next->next;
free(temp);
}
return;
}
MyLinkedList* cur=obj->next;
for(int i=1;cur!=NULL;i++){
if(i==index){
MyLinkedList* temp=cur->next; //要删除的节点
if(temp!=NULL){
cur->next=cur->next->next;
free(temp);
}
return;
}else{
cur=cur->next;
}
}
}
// 8.释放节点
void myLinkedListFree(MyLinkedList* obj) {
while(obj!=NULL){
MyLinkedList *temp=obj;
obj=obj->next;
free(temp);
}
}
/**
* MyLinkedList* obj = myLinkedListCreate();
* int param_1 = myLinkedListGet(obj, index);
* myLinkedListAddAtHead(obj, val);
* myLinkedListAddAtTail(obj, val);
* myLinkedListAddAtIndex(obj, index, val);
* myLinkedListDeleteAtIndex(obj, index);
* myLinkedListFree(obj);
*/
移除元素
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val){
typedef struct ListNode ListNode;
//虚拟头结点
ListNode *dummyHead;
dummyHead=(ListNode*)malloc(sizeof(ListNode));
dummyHead->next=head;
//指针cur从虚拟头结点开始遍历到要删除节点的前一个节点
ListNode *cur=dummyHead;
while(cur->next!=NULL){
if(cur->next->val==val){
ListNode*temp=cur->next; //保存要去除的节点
cur->next=cur->next->next;
free(temp); //释放内存
}else{
cur=cur->next;
}
}
head=dummyHead->next; //新的头结点
free(dummyHead); //释放虚拟头结点
return head;
}
翻转链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head){
struct ListNode*temp; //保存下一个节点
struct ListNode*cur=head; //指向头节点
struct ListNode*pre=NULL;
//pre---cur---temp 交换后 temp--cur---pre
while(cur!=NULL){
temp=cur->next; //先保存下一个节点
cur->next=pre; //下一个节点指针指向前一个节点
// 同时向前移动
pre=cur;
cur=temp;
}
return pre;
}
两两交换链表节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* swapPairs(struct ListNode* head){
typedef struct ListNode ListNode;
ListNode* dummyHead=(ListNode*)malloc(sizeof(ListNode));
dummyHead->next=head;
ListNode* cur=dummyHead;
// 以cur 1 2 3 4为例
while(cur->next!=NULL && cur->next->next!=NULL){
ListNode* temp1=cur->next; //temp1保存节点1
ListNode* temp2=cur->next->next->next; //temp2保存节点3
cur->next=cur->next->next; //cur 2
cur->next->next= temp1; //cur 2 1
cur->next->next->next= temp2; //cur 2 1 3
cur=cur->next->next; //cur移动到第二组的头节点,节点2的位置
}
head=dummyHead->next;
free(dummyHead);
return head;
}
删除倒数第N个节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
typedef struct ListNode ListNode;
ListNode* dummyHead=(ListNode*)malloc(sizeof(ListNode));
dummyHead->next=head;
ListNode* fast=dummyHead;
ListNode* slow=dummyHead;
while(n-- && fast!=NULL){ //fast指针走n步
fast=fast->next;
}
fast=fast->next; //fast指针走了n+1步
while(fast!=NULL){
fast=fast->next;
slow=slow->next;
}
//此时slow走到要删除节点的前一个节点
slow->next=slow->next->next;
head=dummyHead->next;
free(dummyHead);
return head;
}
相交节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
typedef struct ListNode ListNode;
ListNode* curA=NULL;
ListNode* curB=NULL;
int lenA=0,lenB=0,gapLen=0;
curA=headA;
while(curA!=NULL){
lenA++;
curA=curA->next;
}
curB=headB;
while(curB!=NULL){
lenB++;
curB=curB->next;
}
if(lenA>lenB){
curA=headA;
curB=headB;
gapLen=lenA-lenB;
}else{
curA=headB;
curB=headA;
gapLen=lenB-lenA;
}
while(gapLen--){
curA=curA->next;
}
while(curA!=NULL){
if(curA==curB){ //比较的是指针相等而不是数值相等,不能用curA->val==curB->val
return curA;
}
curA=curA->next;
curB=curB->next;
}
return NULL;
}
环形链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head) {
typedef struct ListNode ListNode;
ListNode *slow=head,*fast=head;
while(fast && fast->next!=NULL){
slow=slow->next;
fast=fast->next->next;
if(slow == fast){ //相遇
ListNode *f=head,*l=fast; //f从起点出发,l从相遇点出发
while(f!=l){
f=f->next;
l=l->next;
}
return f;
}
}
return NULL;
}
栈和队列
双栈实现队列
typedef struct {
int stackInTop,stackOutTop; //两个栈的栈顶指针
int stackIn[100],stackOut[100];
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* queue=(MyQueue*)malloc(sizeof(MyQueue));
queue->stackInTop=0;
queue->stackOutTop=0;
return queue;
}
void myQueuePush(MyQueue* obj, int x) {
obj->stackIn[(obj->stackInTop)++]=x;
}
int myQueuePop(MyQueue* obj) {
int stackInTop=obj->stackInTop; //初始化栈顶指针
int stackOutTop=obj->stackOutTop;
if(stackOutTop==0){ //输出栈为空,则将输入栈的内容全部复制到输出栈
while(stackInTop>0){
obj->stackOut[stackOutTop++]=obj->stackIn[--stackInTop]; //注意是先--,后++
}
}
int top=obj->stackOut[--stackOutTop]; //保存并弹出要出栈的元素
while(stackOutTop>0){ //将输出栈的内容放回输入栈
obj->stackIn[stackInTop++]=obj->stackOut[--stackOutTop];
}
obj->stackInTop=stackInTop; //更新栈顶指针
obj->stackOutTop=stackOutTop;
return top;
}
int myQueuePeek(MyQueue* obj) {
return obj->stackIn[0]; //输入栈栈底元素为队头
}
bool myQueueEmpty(MyQueue* obj) {
return obj->stackInTop==0 && obj->stackOutTop==0; //输入输出栈是否同时为空
}
void myQueueFree(MyQueue* obj) {
obj->stackInTop=0; //栈顶指针置为0
obj->stackOutTop=0;
}
/**
* Your MyQueue struct will be instantiated and called as such:
* MyQueue* obj = myQueueCreate();
* myQueuePush(obj, x);
* int param_2 = myQueuePop(obj);
* int param_3 = myQueuePeek(obj);
* bool param_4 = myQueueEmpty(obj);
* myQueueFree(obj);
*/
链表实现栈
//1. 定义链表节点的结构体
typedef struct tagListNode{
struct tagListNode* next;
int val;
}ListNode;
//2. 定义栈顶的指针
typedef struct {
ListNode *top;
} MyStack;
//3. 创建栈
MyStack* myStackCreate() {
MyStack* stk=calloc(1,sizeof(MyStack)); //calloc()在堆区申请动态内存空间
return stk;
}
//4. 入栈 node->next=obj->top
void myStackPush(MyStack* obj, int x) {
ListNode* node=(ListNode*)malloc(sizeof(ListNode));
node->val=x; // 赋值x
node->next=obj->top; // 入栈新元素为新的栈顶
obj->top=node;
}
//5. 出栈 node指向原来的栈顶,obj->top=node->next
int myStackPop(MyStack* obj) {
ListNode* node=obj->top; //指向栈顶
int val=node->val; //出栈元素的值
obj->top=node->next; //新的栈顶
free(node);
return val;
}
//6. 栈顶元素
int myStackTop(MyStack* obj) {
return obj->top->val;
}
//7. 栈是否为空
bool myStackEmpty(MyStack* obj) {
return (obj->top == NULL);
}
//8. 清空栈
void myStackFree(MyStack* obj) {
while(obj->top != NULL){
ListNode *node=obj->top; //保存当前栈顶
obj->top=node->next; //清除当前栈顶
free(node);
}
free(obj);
}
/**
* Your MyStack struct will be instantiated and called as such:
* MyStack* obj = myStackCreate();
* myStackPush(obj, x);
* int param_2 = myStackPop(obj);
* int param_3 = myStackTop(obj);
* bool param_4 = myStackEmpty(obj);
* myStackFree(obj);
*/
括号匹配
//遇到右括号,取出栈顶比较,不匹配返回true
int notMatch(char par,char *stack,int top){
switch(par){
case '}':
return stack[top-1]!='{';
case ')':
return stack[top-1]!='(';
case ']':
return stack[top-1]!='[';
}
return 0;
}
bool isValid(char * s){
int top=0;
char stack[5000];
int len=strlen(s);
for(int i=0;i<len;i++){
//左括号入栈
if(s[i]=='{' || s[i]=='[' || s[i]=='(')
stack[top++]=s[i];
//栈提前为空 或者 不匹配
else if(top==0 || notMatch(s[i],stack,top))
return 0;
//匹配成功弹出
else
top--;
}
// 全部匹配成功则栈为空
return top==0;
}
字母对对碰
//使用栈来保存遍历过的字母
char * removeDuplicates(char * str){
int top=0;
int len=strlen(str);
// 栈大小多开一位,用来存放字符串末尾的'\0'
char* stack=(char*)malloc(sizeof(char)* len+1);
for(int i=0;i<len;i++){
//栈为空 或者 栈顶与当前遍历字母不同
if(top==0 || stack[top-1] != str[i])
stack[top++]=str[i]; //入栈
else
top--; //相同则弹出
}
stack[top]='\0'; //字符串标志
return stack;
}
逆波兰表达式求值
注意c语言中字符串以’\0’结尾,因此取操作数的时候要排除掉’\0’
bool isNumber(char* token){ //字符串以'\0'结尾,因此数字要取[0]处的值
return strlen(token)>1 || '0'<=token[0] && token[0]<='9';
}
int evalRPN(char ** tokens, int tokensSize){
int len=tokensSize;
int stack[len],top=0;
for(int i=0;i<len;i++){
char * token=tokens[i]; //token指向单个字符串
if(isNumber(token)){ //数字直接入栈
stack[top++]=atoi(token); //atoi将字符串转化为整数
}else{
int num2=stack[--top];
int num1=stack[--top];
switch(token[0]){ //token[0]为运算符,除开末尾的'\0'
case '+':
stack[top++]=num1+num2;
break;
case '-':
stack[top++]=num1-num2;
break;
case '*':
stack[top++]=num1*num2;
break;
case '/':
stack[top++]=num1/num2;
break;
}
}
}
return stack[top-1];
}
滑动窗口
- 出队:只要遍历元素nums[i]大于等于队尾元素nums[q[right–]]时,队尾元素弹出。
- 入队:直到nums[i]小于队尾才入队,保证队列对应的元素单调递减
- 队列q存放的是下标,下标对应的元素单调递减,这样队头q[left]存放的是窗口最大值的下标
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize){
int q[numsSize];
int left=0,right=0;
for(int i=0;i<k;i++){
//当前元素大于等于队尾的元素,则将队尾弹出
while(left<right && nums[i]>=nums[q[right-1]]){
right--;
}
//小于则入队,保持队列单减
q[right++]=i;
}
*returnSize=0;
int *ans=malloc(sizeof(int)*numsSize-k+1); //ans保存最大值数组
ans[(*returnSize)++]=nums[q[left]]; //前K个元素的最大值
for(int i=k;i<numsSize;i++){
while(left<right && nums[i]>=nums[q[right-1]]){
right--;
}
q[right++]=i;
while(q[left]<=i-k){
left++; //窗口移动
}
ans[(*returnSize)++]=nums[q[left]]; //当前窗口最大值
}
return ans;
}
二叉树
二叉树定义
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
二叉树递归遍历
前序
void preOrder(struct TreeNode*root,int *res,int *returnSize){
if(root==NULL){
return;
}
res[(*returnSize)++]=root->val; //根节点加入结果数组
preOrder(root->left,res,returnSize);
preOrder(root->right,res,returnSize);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
int *res=(int*)malloc(sizeof(int)*100);
*returnSize=0;
preOrder(root,res,returnSize);
return res;
}
中序
void inOrder(struct TreeNode* node,int* res,int* returnSize){
if(node==NULL){
return;
}
inOrder(node->left,res,returnSize);
res[(*returnSize)++]=node->val;
inOrder(node->right,res,returnSize);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize) {
int *res=(int*)malloc(sizeof(int)* 100);
*returnSize=0;
inOrder(root,res,returnSize);
return res;
}
后序
void postOrder(struct TreeNode* node,int* res,int* returnSize){
if(node==NULL){
return;
}
postOrder(node->left,res,returnSize);
postOrder(node->right,res,returnSize);
res[(*returnSize)++]=node->val;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize) {
int *res=(int*)malloc(sizeof(int)* 100);
*returnSize=0;
postOrder(root,res,returnSize);
return res;
}
二叉树层序遍历
int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes) {
*returnSize=0; //记录层数
if(root==NULL)return NULL;
int **res=(int**)malloc(sizeof(int*) * 2000);
*returnColumnSizes=(int*)malloc(sizeof(int) * 2000); //记录每一层的结点数
struct TreeNode* queue[2000];
struct TreeNode* cur;
int front=0,rear=0;
queue[rear++]=root; //根节点入队
while(front<rear){
int colSize=0,last=rear;
res[*returnSize]=(int*)malloc(sizeof(int)*(last-front)); //保留每一层的结点
while(front<last){
cur=queue[front++];
res[*returnSize][colSize++]=cur->val; //记录当前层的结点
if(cur->left!=NULL){
queue[rear++]=cur->left;
}
if(cur->right!=NULL){
queue[rear++]=cur->right;
}
}
(*returnColumnSizes)[*returnSize]=colSize; //记录当前层结点数
(*returnSize)++; //更新当前层数
}
return res;
}