算法题目之对症下药(一)

在算法题目中,对于不同类型的题目多多少少都有相对应的较为高效的数据结构和算法,这也是体现程序员价值所在的地方。

链表求倒数第k个的题目

这篇文章想分享的链表题目是题干中出现链表求倒数第k个的题目。

链表的特点(区别于数组)即是不连续存储,没有下标,所以不能直接获得想要的第几个元素,而必须从头遍历到想要的位置才能取到对应位置的内容,它的优点是增删比数组来得快,因为可以直接将某一个结点插入到一个链表中或者从一个链表中删除,而不涉及到大量数据的移动。因此在程序设计中,如果增删比较频繁,我们应该优先考虑链表;而查改比较多的,我们应该优先考虑数组

然而算法题目是不会轻易让你好过的,它就是要反其道而行之,有链表的题目一般都会要你拿到第几个或者倒数第几个元素,那么怎么才能让自己的算法显得高效一些呢?有的同学可能会想,既然他反着来,那我们就将链表先转成数组,然后跟操作数组一样去操作它不就完成了吗?虽然这是可行的,但是却显示出了自己编程上的不灵活,怎么他一搞成链表你就一定要转成数组呢?这不就暴露出你对链表不熟了吗?

如果题目是找到链表的第几个元素,相信大家也不会从头将链表转成数组了吧。直接外设一个计数器,遍历一个加一个,加到k直接返回即可,如果遇到链表长度小于k,则返回-1或者null即可。

那如果是查找倒数第几个呢?

对于有链表并且是查找倒数第几个的算法题目,快慢指针算法可以说是比较高效的

题目如下:
输入一个链表,输出该链表中倒数第k个结点。

这是剑指Offer的一道算法题目,类似变形的题目还有输入一个有序链表,找到链表中第k大的元素等

快慢指针就像两兄弟,快指针先行一步,慢指针等着快指针的消息行事。既然是倒数第k个,那我们就让快指针走到最后一个,而慢指针则是我们想要的那个结果,这么一来,慢指针与快指针的距离就是k,这就像快指针与慢指针之间有一条长为k的线,由快指针拉着慢指针走,这样一来,我们的算法只要保证快指针比慢指针快k个位置,快指针走到链表结尾则慢指针就是满足要求的结点
这种算法的时间复杂度为O(n), 代码实现如下:

public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null){
            if(k <= 0)
                slow = slow.next;
            k--;
            fast = fast.next;
        }
        if(k > 0)
            return null;
        else
            return slow;
    }
}

用游标解决数组分组

题目如下:
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

对于这道题我的解法类似于快排:从后往前找奇数,从前往后找偶数,将前面的偶数与后面的奇数交换,当前后两个指针相遇时即已经完成要求

public class Solution {
    public void reOrderArray(int [] array) {
        int temp;
        int length = array.length;
        int left = 0, right = length - 1;
        while(left < right){
        	while(array[left] % 2 == 0)
        		left++;
        	while(array[right] % 2 == 1)
        		right--;
        	if(left > right)
        		break;
        	temp = array[left];
        	array[left] = array[right];
        	array[right] = temp;
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值