zoukankan      html  css  js  c++  java
  • 数据结构与算法——链表(2)

    链表的回文结构

    对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。

    给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

    测试样例:

    1->2->2->1
    返回:true
    

    Java

    具体实现
    /**
    * recognize Palindrome number
    * @return
     */
    public boolean judgePalindrome() {
        if(this.head == null) { //判断链表非空
            return false;
        }else if(this.head.next == null) {
            return true;
        }
        
        Node first = this.head;
        Node second = this.head;
        while(first != null && first.next!= null) { //寻找中间节点
            first = first.next.next;
            second = second.next;
        }
        Node p = second.next; //节点 second 即为中间的节点,若链表为偶数则表示中间第二个
        Node pNext = p.next;
        
        while(p != null) { //将中间节点以后的部分的链表逆置
            p.next = second;
            second = p;
            p = pNext;
            if(p != null) {
                pNext = p.next;
            }
        }
        
        while(head != second) {
            if(head.data != second.data) {
                return false;
            }
            if(head.next == second) {
                return true;
            }
            head = head.next;
            second = second.next;
        }
        return true;
    }
    

    C++

    /*
    struct ListNode {
        int val;
        struct ListNode *next;
        ListNode(int x) : val(x), next(NULL) {}
    };*/
    
    classPalindromeList {
    public:
        bool chkPalindrome(ListNode* A) {
            // write code here
            //A为空时false,A为单个节点时true
            if(A==NULL){
                returnfalse;
            }elseif(A->next==NULL){
                returntrue;
            }
            //快慢指针找出中间节点
            ListNode* quick=A;
            ListNode* slow=A;
            while(quick!=NULL&&quick->next!=NULL){
                quick=quick->next->next;
                slow=slow->next;
            }
            //将中间节点后的指针反转
            ListNode* p=slow->next;
            ListNode* p1=p->next;
    
            while(p!=NULL){
                p->next=slow;
                slow=p;
                p=p1;
                p1=p1->next;
            }
    //从头、尾指针向中间遍历,判断A是否是回文
            while(A!=slow){
                if((A->val)!=(slow->val)){
                    returnfalse;
                }else{
                    if(A->next==slow){
                        returntrue;
                    }
                    A=A->next;
                    slow=slow->next;
                }
            }
            returntrue;
        }
    };
    

    two-sum

    https://www.nowcoder.com/questionTerminal/20ef0972485e41019e39543e8e895b7f

    给出一个整数数组,请在数组中找出两个加起来等于目标值的数,

    你给出的函数twoSum 需要返回这两个数字的下标(index1,index2),需要满足 index1 小于index2.。注意:下标是从1开始的

    假设给出的数组中只存在唯一解

    例如:

    给出的数组为 {2, 7, 11, 15},目标值为9
    输出 ndex1=1, index2=2

    Java

    import java.util.HashMap;
    public class Solution {
        public int[] twoSum(int[] numbers, int target) {
            int n = numbers.length;
            int[] result = new int[2];
            //map里面放 键为target-每个数的结果 值为下标
            //每次放入的时候看是否包含 当前值
            //有的话说明当前值和已包含的值下标的那个元素为需要的结果
            HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
            for(int i=0;i<n;i++){
                if(map.containsKey(numbers[i])){
                    result[0] = map.get(numbers[i])+1;
                    result[1] = i+1;
                    break;
                }
                else{
                    map.put(target - numbers[i], i);
                }
            }
            return result;
        }
    }
    

    C++

    class Solution {
    public:
        vector<int> twoSum(vector<int> &numbers, int target) {
            unordered_map<int, int> hashtable;
            vector<int> result;
            for(int i=0; i<numbers.size(); i++){
                hashtable[numbers[i]] = i;
            }
            for(int i=0; i<numbers.size(); i++){
                const int diff = target - numbers[i];
                if(hashtable.find(diff) != hashtable.end() && hashtable[diff] > i){
                    result.push_back(i+1);
                    result.push_back(hashtable[diff]+1);
                    break;
                }
            }
            return result;
        }
    };
    

    奇数位丢弃

    https://www.nowcoder.com/questionTerminal/196141ecd6eb401da3111748d30e9141

    对于一个由0..n的所有数按升序组成的序列,我们要进行一些筛选,每次我们取当前所有数字中从小到大的第奇数位个的数,并将其丢弃。重复这一过程直到最后剩下一个数。请求出最后剩下的数字。

    输入

    500  //每组数据一行一个数字,为题目中的n(n小于等于1000)。
    

    输出

    255  //一行输出最后剩下的数字。
    

    C

    因为是从0开始,所以第一轮移走的是二进制下最右边为0的位置(从0开始的偶数位置)上的数,然后我们发现第二轮各个number的位置等于number/2,即从number位置到number>>1位置,这时候我们依然移走二进制下最右边为0的位置(1(01) 5(101) 9(1001) ……它们第二轮对应的位置是0, 2, 4),最后剩一个数肯定是0到n中二进制下1最多的那个数,因为它每次的位置都是奇数位置。代码如下

    #include <cstdio>
     
    int main()
    {
        int n;
        while(scanf("%d", &n) != EOF){
            int b = 1;
            while(b <= n + 1){
                b <<= 1;
            }
            printf("%d
    ", (b >> 1) - 1);
        }
        return 0;
    }
    
    import java.util.*;
    public class Main {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            while (sc.hasNext()) {
                int n = sc.nextInt();
                List<Integer> list = new ArrayList<Integer>();
                for (int i = 0; i <= n; i ++ )
                    list.add(i);
                while (list.size() != 1) {
                    // 从0开始list移除一次,i再加一次,i始终指向奇数位
                    for (int i = 0; i < list.size(); i = i + 1)
                        list.remove(i);
                }
                System.out.println(list.get(0));
            }
        }
    }
    
    //常规做法,比较直观,用数组a每次循环清楚记录了每次删除后剩余的元素。
    #include<iostream>
    using namespace std;
    int main(){
        int n,i,a[1001],count;
        while( cin >> n ){
            for(i=0;i<=n;i++)
                a[i] = i;
            count = n+1;
            while( count != 1 ){
                for(i=0;2*i+1<count;i++)
                    a[i]  = a[2*i+1];
                count = i;
            }
            cout << a[0] << endl;
        }
    }
    //特殊思路,每次删除所在数组位置的二进制最右端为0的元素。如0(0)2(10)4(100)
    //剩余的元素1(01)3(11)5(101)下一次其位置变成了之前位置左移一次后的
    // 1(1) 3(10) 5(10) 然后继续按之前规则删除最右端为0的元素。故原始序列中,谁的//二进制下从右往左数,1最多,则最后删除,因每次删除移位后,最右端仍然为1,会保留
    #include<iostream>
    using namespace std;
    int main(){
        int n;
        while( cin >> n ){
            int b = 1;
            while( b <= n )
                /*b = (b<<1) + 1;//或者 用*/ b = b*2 +1;
            cout << (b>>1) << endl;
        }
    }
    
  • 相关阅读:
    《应用Yii1.1和PHP5进行敏捷Web开发》学习笔记(转)
    YII 小模块功能
    Netbeans代码配色主题大搜集
    opensuse 启动巨慢 解决方法 90s多
    opensuse 安装 网易云音乐 rpm netease music
    linux qq rpm deb opensuse
    openSUSE 安装 alien
    第一行代码 Android 第2版
    Android Studio AVD 虚拟机 联网 失败
    docker error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.29/containers/json: open //./pipe/docker_engine: The system cannot find the file specified. In the default daemon configuratio
  • 原文地址:https://www.cnblogs.com/wwj99/p/12200471.html
Copyright © 2011-2022 走看看