【无标题】2022-7-24

 先正序计算每个位置左max

倒序计算每个位置右max

当前水位 = min(左max,右max)-     当前高度

蓄水量为各个位置蓄水量求和

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int trap(int* height, int heightSize){
	int out=0,max=0;
	int *tl=(int*)malloc(sizeof(int)*heightSize);
	memset(tl,0,heightSize);
	for(int i=1;i<heightSize;i++){
		max=max<height[i-1]?height[i-1]:max; 
		tl[i]=max;

	}
	max=0;
	for(int i=heightSize-2;i>0;i--){
		max=max<height[i+1]?height[i+1]:max; 
		int t=max<tl[i]?max:tl[i];
		t=t-height[i];
		if(t>0){
			out+=t;

		}
	}
	return out;
}

 如果喜欢栈顶的甜点的学生存在,那么不管他们在队伍的哪个位置,必定会遍历到他。否则,一定无法继续拿掉栈顶甜点。

int countStudents(int* students, int studentsSize, int* sandwiches, int sandwichesSize){
    int arr[2];
    memset(arr, 0, sizeof(arr));
    for (int i=0; i<studentsSize; ++i) {
        ++arr[students[i]];
    }
    for (int i=0; i<sandwichesSize; ++i) {
        if (arr[sandwiches[i]] == 0) break;
        --arr[sandwiches[i]];
    }
    return arr[0] + arr[1];
}

 

 先使用快慢指针找中点

反转后半部分链表

交叉合并两个链表



void reorderList(struct ListNode* head){

    struct ListNode *tmp = head;
    int ListLen = 1;
    while (tmp->next != NULL) {
        ListLen++;
        tmp = tmp->next;
    }

    struct ListNode **ListArry = malloc(sizeof(struct ListNode*) * ListLen);

    tmp = head;
    int i = 0;
    while (tmp->next != NULL) {
        ListArry[i] = tmp;
        i++;
        tmp = tmp->next;
    }
    ListArry[i] = tmp;

    tmp = head;
    struct ListNode *tmp2 = NULL;
    for (int i = 0; i < ListLen / 2; i++) {
        tmp2 = tmp->next;
        tmp->next = ListArry[ListLen - 1 - i];
        tmp = tmp->next;
        tmp->next = tmp2;
        tmp = tmp->next;
    }

    tmp->next = NULL;
}

 

 

typedef struct minstack{
    int val;
    int size;
    struct minstack *next;
    struct minstack *top;

} MinStack;

/** initialize your data structure here. */


MinStack* minStackCreate() {
    MinStack *root = (MinStack *)malloc(sizeof(MinStack));
    root->next = NULL;
    root->size = 0;
    root->top = NULL;
    return root;
}


void minStackPush(MinStack* obj, int x) {//入栈
    MinStack *node = minStackCreate();
    node->val = x;
    node->next = obj->top;
    obj->top = node;
    obj->size++;
}


void minStackPop(MinStack* obj) {//出栈
    if(obj->size == 0) return;
    MinStack *cur = obj->top;
    obj->top = obj->top->next;
    obj->size--;
    free(cur);
}


int minStackTop(MinStack* obj) {//获取栈顶的值
    if(obj->size == 0) return 0;
    return obj->top->val;
}


int minStackGetMin(MinStack* obj) {
    MinStack *cur = obj;  
    MinStack *top = obj->top; 
    if(cur->size == 0) return 0;
    int minret = cur->top->val;
    int size = cur->size;
    while(size--)
    {
        int temp = cur->top->val;
        minret = minret < temp ? minret : temp;
        cur->top = cur->top->next; 

    }

    cur->top = top; 
    return minret;
}

void minStackFree(MinStack* obj) {
    if(obj->size == 0)
    {
        return;
    }

    while(obj->size > 0)
    {
        MinStack *temp = obj->top;
        obj->top = obj->top->next;
        free(temp);
        obj->size--;
    }
}

 

 

用两个栈实现队列的入队、出队
一个栈只进行入栈,相当于入队
另一个栈只进行出栈,相当于出队

 

typedef struct {
    int top1; //栈1的栈顶指针
    int top2; //栈2的栈顶指针
    int size; //栈的大小
    int count; //队列中的元素个数
    int *S1; //栈1
    int *S2; //栈2
} MyQueue;

/** Initialize your data structure here. */
//初始化两个栈
MyQueue* myQueueCreate() {
    MyQueue* queue = (MyQueue*)malloc(sizeof(MyQueue));
    queue->top1 = -1;
    queue->top2 = -1;
    queue->size = 100;
    queue->count = 0;  //队列中当前元素个数0
    queue->S1 = (int*)malloc(queue->size * sizeof(int));
    queue->S2 = (int*)malloc(queue->size * sizeof(int));

    return queue;
}


void myQueuePush(MyQueue* obj, int x) {
    if(obj->top1 == -1)
    {
        while(obj->top2 != -1)
        {
            obj->S1[++obj->top1] = obj->S2[obj->top2--]; //将栈2中的所有元素保存到栈1
        }
    }
    obj->S1[++obj->top1] = x; //新元素入栈相当于入队
    
    obj->count++; //队列元素个数加一
}

int myQueuePop(MyQueue* obj) {
    if(obj->top2 == -1)
    {
        while(obj->top1 != -1)
        {
            obj->S2[++obj->top2] = obj->S1[obj->top1--]; //将栈1中的元素保存到栈2中
        }
    }
    obj->count--;
    return obj->S2[obj->top2--];

}

/*查看队头元素,即查看栈2的栈顶元素*/
int myQueuePeek(MyQueue* obj) {
    if(obj->top2 == -1)
    {
        while(obj->top1 != -1)
        {
            obj->S2[++obj->top2] = obj->S1[obj->top1--];
        }
    }
    return obj->S2[obj->top2];
}

/*队列为空返回true,否则返回false */
bool myQueueEmpty(MyQueue* obj) {
    if(obj->count == 0)
        return true;
    else
        return false;
}

void myQueueFree(MyQueue* obj) {
    free(obj->S1);
    free(obj->S2);
    free(obj);
}

SVM

想要的就是找到各类样本点到超平面的距离最远,也就是找到最大间隔超平面。任意超平面可以用下面这个线性方程来描述:

w(T)*x+b=0

二维空间点 (x,y) 到直线 Ax+By+C=0 的距离公式是:

\frac{|Ax+By+C|}{\sqrt{A^{2}+B^{2}}}

扩展到 n 维空间后,点 x=(x1,x2…xn) 到直线 wTx+b=0 的距离为:

\frac{|wTx+b|}{||w||}

假设有一个超平面H:ωTx+b=0能正确地将样本划分开来,那么同时也肯定存在两个平行于H的平面H1和H2:
H1:ωTx+b=1
H2:ωTx+b=1

距离超平面 H距离最近的正负样本正好就分别在H1和 H2上,而这样的样本就是 支持向量。

对于任意样本 (xi,yi)有,若 yi=1,即为正样本,满足 ωTxi+b>0;若 yi=−1,即为负样本,满足 ω(T)xi+b<0。
令:

\binom{w(T)+b>=1,yi=+1}{w(T)+b<=1,yi=-1}        

使用之前推出的任意点 xx到超平面的距离的公式,不难发现,超平面H1H1和 H2H2之间的距离是:
d=\frac{2}{||w||}
 

这个东西就叫做 间隔。
而SVM的目标是就是找到一个超平面,使得 间隔取到最大值,同时也要能保证正确地划分正负样本。
超平面由法向量w和截距b决定,法向量指向的一侧为正类,另一侧为负类

函数间隔

在超平面wx+b=0确定的情况下,|wx+b|能够相对地表示点x距离超平面的远近。wx+b的符号与类标记y的符号是否一致能够表示分类是否正确。所以可用变量y(wx+b)来表示分类的正确性及确信度-统计学习方法(李航)

函数间隔可以表示分类预测的正确性及准确度,但是选择分类超平面时,只有函数间隔还不够,因为只要成比例地改变w和b,,比如说2w和2b,超平面并没有改变,但是函数间隔却称为原来的2倍

几何间隔

统计学习方法

最大间隔分类器Maximum Margin Classifier的定义

对一个数据点进行分类,当超平面离数据点的“间隔”越大,分类的确信度(confidence)也越大。所以,为了使得分类的确信度尽量高,需要让所选择的超平面能够最大化这个“间隔”值。这个间隔就是下图中的Gap的一半。

很喜欢统计学习方法中关于最大间隔的描述:

不仅将正负实例点分开,而且对最难分的实例点(离超平面最近的点)也有足够大的确信度将它们分开,这样的超平面应该对未知的新实例有很好的分类预测能力-统计学习方法

统计学习方法中关于最大间隔法

 

虚线上的点便叫做支持向量Support Vector,在线性可分情况下,训练数据集的样本点中与分离超平面最近的样本点的实例

满足公式:y(wx+b)-1=0

在决定分离超平面时只有支持向量起作用

统计学习方法Page:115定义

深入SVM

学习的对偶算法

应用拉格郎日对偶性,通过求解对偶问题(dual problem)得到原始问题(primal problem)的最优解,这就是线性可分支持向量机的对偶算法(dual algorithm),优点为对偶问题更容易求解,引入核函数,进而推广到非线性分类问题

求解步骤

将拉格郎日函数L(w,b,a)分别对w,b求偏导数并令其等于0

将以上的结果代入之前的L

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骑驴_找马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值