剑指offer(1/14)

本文探讨了字符串中寻找唯一字符的算法,包括Java和C++的实现,以及利用归并排序计算数组逆序对的方法,并对两个链表找第一个公共节点的解决方案进行了分析。这些算法涉及字符串遍历、排序和链表操作,对于提升编程技能具有实际价值。
摘要由CSDN通过智能技术生成

第一次只出现一次的字符

在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)

public class Solution {
    public int FirstNotRepeatingChar(String str) {
        int res = -1;
        if(str ==null || str.length() == 0) return res;
        if(str.length() == 1) return 1;
        char[] charArr = str.toCharArray();
        int[] count = new int[128];
        for(int i = 0; i < charArr.length; i++){
            count[charArr[i]]++;
        }
        for(int i = 0; i < count.length; i++){
            if(count[charArr[i]] == 1){
                res = i;
                break;
            }
        }
        return res;
    }
}
class Solution {
public:
    int FirstNotRepeatingChar(string str) {
        if(str.size()==0)
            return -1;
        char ch[256]={0};
        for(int i=0;i<str.size();i++)
            ch[str[i]]++;
        for(int i=0;i<str.size();i++)
            if(ch[str[i]]==1)
                return i;
        return -1;
    }
};

数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

import java.io.*;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String str = br.readLine();
        str = str.substring(1, str.length()-1);
        String[] valueArr = str.split(",");
        int[] array = new int[valueArr.length];
        for (int i = 0; i < valueArr.length; i++) {
            array[i] = Integer.parseInt(valueArr[i]);
        }
        System.out.println(InversePairs(array));
    }
    public static int InversePairs(int [] array) {
        if(array == null) return 0;
        int[] tmp = new int[array.length];
        return mergeSort(array, tmp, 0, array.length-1);
    }
    //归并排序,递归
    private static int mergeSort(int[] array, int[] tmp, int low, int high) {
        if(low >= high) return 0;
        int res = 0, mid = low + (high - low) / 2;
        res += mergeSort(array, tmp, low, mid);
        res %= 1000000007;
        res += mergeSort(array, tmp, mid + 1, high);
        res %= 1000000007;
        res += merge(array, tmp, low, mid, high);
        res %= 1000000007;
        return res;
    }
    //归并排序,合并
    private static int merge(int[] array, int[] tmp, int low, int mid, int high) {
        int i1 = low, i2 = mid + 1,k = low;
        int res = 0;
        while(i1 <= mid && i2 <= high) {
            if(array[i1] > array[i2]) {
                res += mid - i1 + 1;
                res %= 1000000007;
                tmp[k++] = array[i2++];
            } else
                tmp[k++] = array[i1++];
        }
        while(i1 <= mid)
            tmp[k++] = array[i1++];
        while(i2 <= high)
            tmp[k++] = array[i2++];
        for (int i = low; i <= high; i++)
            array[i] = tmp[i];
        return res;
    }
}
static const auto io_sync_off = []() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    return nullptr;
}();
class Solution {
    public:
    int InversePairs(vector<int> data) {
        if (data.size() < 2) {
            return 0;
        }
        long long count = 0;
        int len=data.size();
        vector<int> tmp(data.begin(),data.end());
         
        count = InversePairs(data,tmp,0,len-1);
        return count%1000000007;
          
    }
    private:
    long long InversePairs(vector<int>& data, vector<int>& copy, int low,int high) {
        if (low == high) {
            copy[low] = data[low];
            return 0;
        }
        long long left;
        long long right;
        int length = (high - low) >> 2;
        left = InversePairs(copy,data,low,(low+(length)));
        right = InversePairs(copy,data,(low+(length)+1),high);
        int i = low + (length);
        int j = high;
        int copy_index = high;
        long long count = 0;
        while (i >= low && j >= (low+(length)+1)) {
            if (data[i] > data[j]) {
                count += j - (low + (length));
                copy[copy_index--] = data[i--];
            } else {
                copy[copy_index--] = data[j--];
            }
               
        }
        for (; i >= low; i--) {
            copy[copy_index--] = data[i];
        }
        for (; j>= (low+(length)+1); j--) {
            copy[copy_index--] = data[j];
        }
        return left + count + right;
    }
       
    long long InversePairsCore(vector<int> &data,vector<int> &tmp,int start,int end)
    {
        if(start==end)
        {
            tmp[start]=data[start];
            return 0;
        }
        int length=(end-start) >> 2;
        long long leftCount = InversePairsCore(data,tmp,start,(start+(length)));
        long long rightCount = InversePairsCore(data,tmp,(start+(length)+1),end);
        int index1 = start+length;
        int index2 = end;
        int index3=end;
        long long count=0;
        while(index1>=start&&index2>=start+(length)+1)
        {
            if(data[index1]>data[index2])
            {
                count+=index2-start-length;
                tmp[index3--]=data[index1--];
            }
            else
            {
                tmp[index3--]=data[index2--];
            }
        }
        for(;index1>=start;index1--)
            tmp[index3--]=data[index1];
        for(;index2>=start+(length)+1;index2--)
            tmp[index3--]=data[index2];
        return leftCount+rightCount+count;
    }
};

两个链表的第一个公共节点

输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        if(pHead1==null || pHead2==null){
            return null;
        }
        ListNode p1 = pHead1;
        ListNode p2 = pHead2;
        while(p1 != p2){
            p1 = p1.next;
            p2 = p2.next;
            if(p1 != p2){
                if(p1 == null){
                    p1 = pHead2;
                }
                if(p2 == null){
                    p2 = pHead1;
                }
            }
        }
        return p1;
    }
}
/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) {
        int len1 = findListLenth(pHead1);
        int len2 = findListLenth(pHead2);
        if(len1 > len2){
            pHead1 = walkStep(pHead1,len1 - len2);
        }else{
            pHead2 = walkStep(pHead2,len2 - len1);
        }
        while(pHead1 != NULL){
            if(pHead1 == pHead2) return pHead1;
            pHead1 = pHead1->next;
            pHead2 = pHead2->next;
        }
        return NULL;
    } 
    int findListLenth(ListNode *pHead1){
        if(pHead1 == NULL) return 0;
        int sum = 1;
        while(pHead1 = pHead1->next) sum++;
        return sum;
    }
    ListNode* walkStep(ListNode *pHead1, int step){
        while(step--){
            pHead1 = pHead1->next;
        }
        return pHead1;
    }
};

       /*
        假定 List1长度: a+n  List2 长度:b+n, 且 a<b
        那么 p1 会先到链表尾部, 这时p2 走到 a+n位置,将p1换成List2头部
        接着p2 再走b+n-(n+a) =b-a 步到链表尾部,这时p1也走到List2的b-a位置,还差a步就到可能的第一个公共节点。
        将p2 换成 List1头部,p2走a步也到可能的第一个公共节点。如果恰好p1==p2,那么p1就是第一个公共节点。  或者p1和p2一起走n步到达列表尾部,二者没有公共节点,退出循环。 同理a>=b.
        时间复杂度O(n+a+b)
        ListNode* p1 = pHead1;
        ListNode* p2 = pHead2;
        while(p1 != p2) {
            if(p1 != NULL) p1 = p1->next;   
            if(p2 != NULL) p2 = p2->next;
            if(p1 != p2) {                  
                if(p1 == NULL) p1 = pHead2;
                if(p2 == NULL) p2 = pHead1;
            }
        }
        return p1;
     
}
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值