2021-5-26学习记录

1 尝试来写一个程序,来进行二分查找的模仿。但是返回的是相同元素的最左边或最右边的元素

如果是一般的查找。也就是,当mid的对应元素等于target的时候,直接return。必须要用
while(left<=right)。不然会导致错误。

如果想要查找相同元素中最左边的那个的话,一个重要的点就是当mid对应元素等于target的
时候,不要直接返回,而是将right只想mid。
int find2_left(int a[], int start, int end,int target) //在start和end之间查找
{
int mid = 0;
while(start <= end) //当相等的时候,就进行退出就行.如果是<=的话,会死循环,在这种思路下
{
cout<<"start= "<<start<<endl;
cout<<"end= "<<end<<endl;
mid = (start+end)/2;
cout<<"mid= "<<mid<<endl;
if(a[mid] == target)
{
//cout<<"end "<<mid<<endl;
end = mid-1; //这样可以实现定位到最左边的元素的左边一个元素
//cout<<end<<endl;
//return mid;
}
else{
if(a[mid]<target)
{
start = mid+1;
}
else{
end = mid -1;
}
}
}
return end+1;
}

int find2_right(int a[], int start, int end,int target) //在start和end之间查找
{
int mid = 0;
while(start <= end) //当相等的时候,就进行退出就行.如果是<=的话,会死循环,在这种思路下
{
cout<<"start= "<<start<<endl;
cout<<"end= "<<end<<endl;
mid = (start+end)/2;
cout<<"mid= "<<mid<<endl;
if(a[mid] == target)
{
//cout<<"end "<<mid<<endl;
start = mid+1; //这样可以实现定位到最左边的元素的左边一个元素
//cout<<end<<endl;
//return mid;
}
else{
if(a[mid]<target)
{
start = mid+1;
}
else{
end = mid -1;
}
}
}
return start-1;
}

int a[10] = {1,2,3,4,5,5,5,5,7,7};
int b[] = {3,3,3};
int c[] = {1,2,3,4,5};
int index = find2_left(a, 0, 9, 5);
//cout<<index<<endl;

int index2 = find2_right(a, 0, 9, 7);
cout<<index2<<endl;

2 最长递增子序列LIS
题目描述:
给定数组arr,设长度为n,输出arr的最长递增子序列。
(如果有多个答案,请输出其中字典序最小的)
思路:
两种方法:
1 动态规划:在于实现状态的转移。对于求两个序列的公共字串等这些的时候
构建一个二维数组。这道题只是涉及到一个序列,也不需要使用二维数组。
维护这样的一个状态值:一个单元的状态是以这个单元作为结尾的最长递增子序列。
如果我知道这个单元前面所有单元的状态值,那么我就可以通过找到一个前面的元素,这个元素
比这个单元要小,然后,可以状态为这个单元的状态+1.相当与接到这个元素的后面。当然,
任何一个前面的比自己小的元素,都可以进行+1,我们要找出+1之后最大的值,来作为状态值。

在找到最小的字典序的子序列的时候,需要进行从后向前的查找。并且是(假设最小子序列
长度为n)先查找dp状态值为n的元素。查找到第一个状态值为n的元素之后,再去查找状态值为
n-1的元素。

2 维护一个数组并利用二分查找来进行替换
当要插入的元素比末尾元素大的时候,就直接插入到末尾。如果比末尾元素小的话,就替换
第一个比他大的元素。并且要记下每一个元素插入的对应index。
然后利用1方法中查找的方法来进行查找LIS。

vector<int> LIS(vector<int>& arr) {
        // write code here
        int nums[arr.size()]; 
        int temp[arr.size()];
        nums[0] = 0;
        int tempIndex = 0;
        temp[tempIndex] = arr[0];
        for(int i=1;i<arr.size();i++) //进行构建
        {
            int left =0, right = tempIndex;
            if(arr[i]>temp[tempIndex])
            {
                ++tempIndex;
                temp[tempIndex] = arr[i];
                nums[i] = tempIndex;
            }
            else{
                //查找到第一个大于这个数的值,然后替换掉他
                while(left<=right)
                {
                    int mid = (left+right)/2;
                    if(temp[mid] > arr[i])
                    {
                        right = mid-1;
                    }
                    else{ //>=
                        left = mid+1;
                    }
                }
                temp[left] = arr[i];
                nums[i] = left;
            }
        }
        
        //根据nums来查找
        vector<int> res(tempIndex+1); //这个size的
        for(int i=arr.size()-1;i>=0;i--)
        {
            if(nums[i] == tempIndex)
            {
                res[tempIndex] = arr[i];
                --tempIndex;
            }
        }
        return res;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值